commit 53db33b84b02c9165e20ab17595ac52ca6238b2f
parent 080b655cba9f5a34f0f72c2d26548d9511f02f50
Author: dwrz <dwrz@dwrz.net>
Date: Wed, 15 Oct 2025 00:30:52 +0000
Add statusbar config
Diffstat:
1 file changed, 148 insertions(+), 0 deletions(-)
diff --git a/cmd/statusbar/config/config.go b/cmd/statusbar/config/config.go
@@ -0,0 +1,148 @@
+package config
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+
+ "code.dwrz.net/src/pkg/statusbar"
+ "code.dwrz.net/src/pkg/statusbar/cpu"
+ "code.dwrz.net/src/pkg/statusbar/datetime"
+ "code.dwrz.net/src/pkg/statusbar/disk"
+ "code.dwrz.net/src/pkg/statusbar/eth"
+ "code.dwrz.net/src/pkg/statusbar/light"
+ "code.dwrz.net/src/pkg/statusbar/memory"
+ "code.dwrz.net/src/pkg/statusbar/mic"
+ "code.dwrz.net/src/pkg/statusbar/power"
+ "code.dwrz.net/src/pkg/statusbar/temp"
+ "code.dwrz.net/src/pkg/statusbar/volume"
+ "code.dwrz.net/src/pkg/statusbar/wlan"
+ "code.dwrz.net/src/pkg/statusbar/wwan"
+)
+
+// Config corresponds to the top-level JSON object.
+type Config struct {
+ Separator string `json:"separator"`
+ Timezone string `json:"timezone"`
+ Blocks []BlockConfig `json:"blocks"`
+}
+
+// BlockConfig holds the configuration for a single block.
+// Params are kept as raw JSON to be parsed into a specific struct later.
+type BlockConfig struct {
+ Datetime *datetime.Config `json:"datetime,omitempty"`
+ Disk *disk.Config `json:"disk,omitempty"`
+ Eth *eth.Config `json:"eth,omitempty"`
+ Name string `json:"name,omitempty"`
+ Power *power.Config `json:"power,omitempty"`
+ Temp *temp.Config `json:"temp,omitempty"`
+ WLAN *wlan.Config `json:"wlan,omitempty"`
+ WWAN *wwan.Config `json:"wwan,omitempty"`
+}
+
+// Load reads the config file and returns the Config and an instantiated slice
+// of Blocks.
+func Load() (*Config, []statusbar.Block, error) {
+ configDir, err := os.UserConfigDir()
+ if err != nil {
+ return nil, nil, fmt.Errorf(
+ "failed to get user config dir: %v", err,
+ )
+ }
+ confPath := filepath.Join(configDir, "statusbar", "config.json")
+ confBytes, err := os.ReadFile(confPath)
+ if err != nil {
+ return nil, nil, fmt.Errorf(
+ "failed to read config file %s: %v", confPath, err,
+ )
+ }
+
+ var cfg Config
+ if err := json.Unmarshal(confBytes, &cfg); err != nil {
+ return nil, nil, fmt.Errorf(
+ "failed to parse config json: %v", err,
+ )
+ }
+
+ var blocks = make([]statusbar.Block, 0, len(cfg.Blocks))
+ for _, bconf := range cfg.Blocks {
+ block, err := CreateBlock(bconf, &cfg)
+ if err != nil {
+ return nil, nil, fmt.Errorf(
+ "failed to instantiate block '%s': %v",
+ bconf.Name, err,
+ )
+ }
+ if block != nil {
+ blocks = append(blocks, block)
+ }
+ }
+
+ return &cfg, blocks, nil
+}
+
+// CreateBlock creates a single block based on its configuration.
+func CreateBlock(bconf BlockConfig, cfg *Config) (statusbar.Block, error) {
+ switch bconf.Name {
+ case "cpu":
+ return cpu.New(), nil
+ case "datetime":
+ var conf datetime.Config
+ if bconf.Datetime != nil {
+ conf = *bconf.Datetime
+ }
+
+ if conf.Timezone == "" {
+ conf.Timezone = cfg.Timezone
+ }
+
+ if conf.Format == "" {
+ now := time.Now()
+ yearEnd := time.Date(
+ now.Year()+1, 1, 1, 0, 0, 0, 0, time.UTC,
+ ).AddDate(0, 0, -1)
+ conf.Format = fmt.Sprintf(
+ "+%%Y-%%m-%%d %%u/7 %%W/52 %%j/%d %%H:%%M %%Z",
+ yearEnd.YearDay(),
+ )
+ }
+ return datetime.New(conf), nil
+ case "disk":
+ return disk.New(bconf.Disk.Mounts...), nil
+ case "eth":
+ return eth.New(bconf.Eth.Iface), nil
+ case "light":
+ return light.New(), nil
+ case "memory":
+ return memory.New(), nil
+ case "mic":
+ return mic.New(), nil
+ case "power":
+ var path = power.Path
+ if bconf.Power != nil && bconf.Power.Path != "" {
+ path = bconf.Power.Path
+ }
+ return power.New(path), nil
+ case "temp":
+ var tconf temp.Config
+ if bconf.Temp != nil {
+ tconf = *bconf.Temp
+ }
+ return temp.New(tconf), nil
+ case "volume":
+ return volume.New(), nil
+ case "wlan":
+ var iface = "wlan0"
+ if bconf.WLAN != nil && bconf.WLAN.Iface != "" {
+ iface = bconf.WLAN.Iface
+ }
+ return wlan.New(iface), nil
+ case "wwan":
+ return wwan.New(bconf.WWAN.Iface), nil
+
+ default:
+ return nil, fmt.Errorf("unknown block type")
+ }
+}