From b422402ffc3b3e48f859c72df0353900ecd800b6 Mon Sep 17 00:00:00 2001 From: MDietermann Date: Tue, 14 Apr 2026 13:07:08 +0200 Subject: [PATCH] feat(theming): apply writes four tool configs to $HOME --- internal/theming/theming.go | 48 ++++++++++++++++++++++++++++++++ internal/theming/theming_test.go | 39 ++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/internal/theming/theming.go b/internal/theming/theming.go index 9cffc8d..bc176bd 100644 --- a/internal/theming/theming.go +++ b/internal/theming/theming.go @@ -7,9 +7,13 @@ import ( "embed" "fmt" "io/fs" + "os" "path/filepath" "sort" + "strings" + "github.com/MDietermann/ArduinoArchSetup/internal/config" + "github.com/MDietermann/ArduinoArchSetup/internal/platform" "gopkg.in/yaml.v3" ) @@ -95,3 +99,47 @@ func Get(id string) (Theme, bool) { } return Theme{}, false } + +// toolConfig describes one tool's config file: its asset name under +// assets// and its user-config destination relative to $HOME. +type toolConfig struct { + Asset string // e.g. "starship.toml" + DestRel string // e.g. ".config/starship.toml" +} + +var toolConfigs = []toolConfig{ + {"starship.toml", ".config/starship.toml"}, + {"zellij.kdl", ".config/zellij/config.kdl"}, + {"yazi.toml", ".config/yazi/theme.toml"}, + {"lazygit.yml", ".config/lazygit/config.yml"}, +} + +// Apply writes each tool's theme config to the user's home directory. +// Task 3 adds overlay-file update; Task 4 adds NvChad chadrc rewrite. +func Apply(cfg config.Config, themeID string) error { + th, ok := Get(themeID) + if !ok { + ids := make([]string, 0, len(discovered)) + for _, t := range discovered { + ids = append(ids, t.ID) + } + return fmt.Errorf("unknown theme %q; valid: %s", themeID, strings.Join(ids, ", ")) + } + home, err := os.UserHomeDir() + if err != nil { + return err + } + + for _, tc := range toolConfigs { + data, err := assetsFS.ReadFile(filepath.Join("assets", th.ID, tc.Asset)) + if err != nil { + return fmt.Errorf("read asset %s: %w", tc.Asset, err) + } + dst := filepath.Join(home, tc.DestRel) + if err := platform.WriteUserFile(dst, data, 0o644); err != nil { + return fmt.Errorf("write %s: %w", tc.DestRel, err) + } + } + _ = cfg // overlay update lands in Task 3 + return nil +} diff --git a/internal/theming/theming_test.go b/internal/theming/theming_test.go index ec3cf24..e7366cf 100644 --- a/internal/theming/theming_test.go +++ b/internal/theming/theming_test.go @@ -1,7 +1,12 @@ package theming import ( + "os" + "path/filepath" + "strings" "testing" + + "github.com/MDietermann/ArduinoArchSetup/internal/config" ) func TestListDiscoversThemes(t *testing.T) { @@ -40,3 +45,37 @@ func TestListIsSortedByID(t *testing.T) { } } } + +func TestApplyWritesFourToolConfigs(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + if err := Apply(config.Config{}, "gruvbox"); err != nil { + t.Fatal(err) + } + + checks := []struct{ rel, wantPrefix string }{ + {".config/starship.toml", "palette"}, + {".config/zellij/config.kdl", "theme"}, + {".config/yazi/theme.toml", ""}, + {".config/lazygit/config.yml", "gui"}, + } + for _, c := range checks { + data, err := os.ReadFile(filepath.Join(home, c.rel)) + if err != nil { + t.Errorf("%s missing: %v", c.rel, err) + continue + } + if len(data) == 0 { + t.Errorf("%s empty", c.rel) + } + if c.wantPrefix != "" && !strings.HasPrefix(strings.TrimSpace(string(data)), c.wantPrefix) { + t.Errorf("%s: want prefix %q, got %q", c.rel, c.wantPrefix, string(data[:min(len(data), 40)])) + } + } +} + +func TestApplyUnknownThemeErrors(t *testing.T) { + if err := Apply(config.Config{}, "does-not-exist"); err == nil { + t.Fatal("want error on unknown theme") + } +}