From b2a1b4fe2a8e546564f34afe610c5b5b24c49b7a Mon Sep 17 00:00:00 2001 From: dwrz Date: Mon, 26 Oct 2026 22:26:05 +0000 Subject: [PATCH] Add statusbar config --- cmd/statusbar/config/config.go | 159 +++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 cmd/statusbar/config/config.go diff --git a/cmd/statusbar/config/config.go b/cmd/statusbar/config/config.go new file mode 100644 index 0000000..5f7f6cc --- /dev/null +++ b/cmd/statusbar/config/config.go @@ -0,0 +1,159 @@ +package config + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "time" + + "code.chimeric.al/dwrz/statusbar/internal/statusbar" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/cpu" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/datetime" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/disk" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/eth" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/light" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/memory" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/mic" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/mlight" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/power" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/temp" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/volume" + "code.chimeric.al/dwrz/statusbar/internal/statusbar/wlan" + "code.chimeric.al/dwrz/statusbar/internal/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. +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) { + cfgDir, err := os.UserConfigDir() + if err != nil { + return nil, nil, fmt.Errorf( + "failed to get user config dir: %w", err, + ) + } + cfgPath := filepath.Join(cfgDir, "statusbar", "config.json") + cfgBytes, err := os.ReadFile(cfgPath) + if err != nil { + return nil, nil, fmt.Errorf( + "failed to read config file %s: %w", cfgPath, err, + ) + } + + var cfg Config + if err := json.Unmarshal(cfgBytes, &cfg); err != nil { + return nil, nil, fmt.Errorf( + "failed to parse config json: %w", 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': %w", + 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": + if bconf.Disk == nil || len(bconf.Disk.Mounts) == 0 { + return nil, fmt.Errorf("missing disk mounts") + } + return disk.New(bconf.Disk.Mounts...), nil + case "eth": + if bconf.Eth == nil || bconf.Eth.Iface == "" { + return nil, fmt.Errorf("missing eth interface") + } + return eth.New(bconf.Eth.Iface), nil + case "light": + return light.New(), nil + case "mlight": + return mlight.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": + if bconf.WWAN == nil || bconf.WWAN.Iface == "" { + return nil, fmt.Errorf("missing wwan interface") + } + return wwan.New(bconf.WWAN.Iface), nil + + default: + return nil, fmt.Errorf("unknown block type") + } +}