commit 2f35c9dd34f442c64850e3b77463c687408fcf1b Author: Jonathan DeMasi Date: Fri Feb 27 21:20:08 2026 -0700 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..10986d8 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +build: + go build -o bin/gobar ./cmd/gobar + +test: + go test ./... diff --git a/README.md b/README.md new file mode 100644 index 0000000..06349ca --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# gobar +A shitty program to update dwlb and other dwm/dwl status bars by writing to a file or stdout. While not as extensible as something like someblocks, this program aims to be easy to run as a userspace daemon. It's extremely lightweight and extensible. diff --git a/cmd/gobar/main.go b/cmd/gobar/main.go new file mode 100644 index 0000000..751de64 --- /dev/null +++ b/cmd/gobar/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "context" + "os" + "os/signal" + "syscall" + + "git.jthan.io/jonathan/gobar/internal/config" + "git.jthan.io/jonathan/gobar/internal/daemon" +) + +func main() { + ctx, stop := signal.NotifyContext( + context.Background(), + os.Interrupt, + syscall.SIGTERM, + ) + defer stop() + + cfg := config.Default() + + if err := daemon.Run(ctx, cfg); err != nil { + os.Exit(1) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8bdb52a --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.jthan.io/jonathan/gobar + +go 1.25.0 diff --git a/internal/collectors/battery.go b/internal/collectors/battery.go new file mode 100644 index 0000000..9f1676b --- /dev/null +++ b/internal/collectors/battery.go @@ -0,0 +1 @@ +package collectors diff --git a/internal/collectors/collector.go b/internal/collectors/collector.go new file mode 100644 index 0000000..20447d7 --- /dev/null +++ b/internal/collectors/collector.go @@ -0,0 +1,33 @@ +package collectors + +type StatusInfo struct { + CPULoad1 float32 + CPULoad5 float32 + CPULoad15 float32 + Year int + Month int + Day int + Hour int + Minute int + Second int + BatteryPercent int + BatteryStatus string +} + +func Collect() (*StatusInfo, error) { + year, month, day, hour, minute, second := datetime() + cpuLoad1, cpuLoad5, cpuLoad15 := cpuLoad() + return &StatusInfo{ + CPULoad1: cpuLoad1, + CPULoad5: cpuLoad5, + CPULoad15: cpuLoad15, + Year: year, + Month: int(month), + Day: day, + Hour: hour, + Minute: minute, + Second: second, + BatteryPercent: 100, + BatteryStatus: "Charging", + }, nil +} diff --git a/internal/collectors/cpu.go b/internal/collectors/cpu.go new file mode 100644 index 0000000..69c373b --- /dev/null +++ b/internal/collectors/cpu.go @@ -0,0 +1,45 @@ +package collectors + +import ( + "bufio" + "log" + "os" + "strconv" + "strings" +) + +func strToFloat32(input string) (float32) { + f64, err := strconv.ParseFloat(input, 32) + if err != nil { + log.Fatal(err) + } + f32 := float32(f64) + return f32 +} + +func cpuLoad() (load1, load5, load15 float32) { + const filePath string = "/proc/loadavg" + var firstLine string + + file, err := os.Open(filePath) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + if scanner.Scan() { + firstLine = scanner.Text() + } + + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + + loadAverages := strings.Fields(firstLine) + load1 = strToFloat32(loadAverages[0]) + load5 = strToFloat32(loadAverages[1]) + load15 = strToFloat32(loadAverages[2]) + return load1, load5, load15 +} diff --git a/internal/collectors/datetime.go b/internal/collectors/datetime.go new file mode 100644 index 0000000..d6edb5f --- /dev/null +++ b/internal/collectors/datetime.go @@ -0,0 +1,12 @@ +package collectors + +import ( + "time" +) + +func datetime() (year int, month time.Month, day, hour, minute, second int){ + currentTime := time.Now() + year, month, day = currentTime.Date() + hour, minute, second = currentTime.Clock() + return year, month, day, hour, minute, second +} diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..ec04768 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,15 @@ +package config + +import ( + "time" +) + +type Config struct { + Interval time.Duration +} + +func Default() Config { + return Config{ + Interval: 30 * time.Second, + } +} diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go new file mode 100644 index 0000000..d406c4f --- /dev/null +++ b/internal/daemon/daemon.go @@ -0,0 +1,40 @@ +package daemon + +import ( + "context" + "log" + "time" + + "git.jthan.io/jonathan/gobar/internal/config" + "git.jthan.io/jonathan/gobar/internal/collectors" + "git.jthan.io/jonathan/gobar/internal/output" +) + +func Run(ctx context.Context, cfg config.Config) error { + ticker := time.NewTicker(cfg.Interval) + defer ticker.Stop() + + log.Printf("daemon started (interval=%s)", cfg.Interval) + + for { + select { + + case <-ctx.Done(): + log.Println("daemon shutting down") + return nil + + case <-ticker.C: + runOnce(ctx) + } + } +} + +func runOnce(ctx context.Context) { + m, err := collectors.Collect() + if err != nil { + log.Println("collect error:", err) + return + } + + output.Print(m) +} diff --git a/internal/output/stdout.go b/internal/output/stdout.go new file mode 100644 index 0000000..98f6b0e --- /dev/null +++ b/internal/output/stdout.go @@ -0,0 +1,20 @@ +package output + +import ( + "fmt" + "git.jthan.io/jonathan/gobar/internal/collectors" +) + +func Print(c *collectors.StatusInfo) { + fmt.Printf( + "LOAD: %.2f %.2f %.2f | %d-%d-%d %d:%d\n", + c.CPULoad1, + c.CPULoad5, + c.CPULoad15, + c.Year, + c.Month, + c.Day, + c.Hour, + c.Minute, + ) +}