diff --git a/internal/theming/theming.go b/internal/theming/theming.go index bc176bd..b1369b4 100644 --- a/internal/theming/theming.go +++ b/internal/theming/theming.go @@ -140,6 +140,52 @@ func Apply(cfg config.Config, themeID string) error { return fmt.Errorf("write %s: %w", tc.DestRel, err) } } - _ = cfg // overlay update lands in Task 3 + _ = cfg // overlay carries config state; overlay file update below + if err := updateOverlayActive(th.ID); err != nil { + return fmt.Errorf("update overlay: %w", err) + } return nil } + +// updateOverlayActive rewrites ~/.config/archduino/overlay.yaml so that +// theme_overrides.__active reflects the selected theme, preserving all +// other keys via a generic map round-trip. +func updateOverlayActive(themeID string) error { + home, err := os.UserHomeDir() + if err != nil { + return err + } + path := filepath.Join(home, ".config", "archduino", "overlay.yaml") + + var root map[string]any + if data, err := os.ReadFile(path); err == nil { + if err := yaml.Unmarshal(data, &root); err != nil { + return fmt.Errorf("parse overlay: %w", err) + } + } + if root == nil { + root = map[string]any{} + } + + if _, ok := root["version"]; !ok { + root["version"] = 1 + } + + var overrides map[string]any + if raw, ok := root["theme_overrides"]; ok { + if m, ok := raw.(map[string]any); ok { + overrides = m + } + } + if overrides == nil { + overrides = map[string]any{} + } + overrides["__active"] = themeID + root["theme_overrides"] = overrides + + out, err := yaml.Marshal(root) + if err != nil { + return err + } + return platform.WriteUserFile(path, out, 0o644) +} diff --git a/internal/theming/theming_test.go b/internal/theming/theming_test.go index e7366cf..0e5f02c 100644 --- a/internal/theming/theming_test.go +++ b/internal/theming/theming_test.go @@ -79,3 +79,41 @@ func TestApplyUnknownThemeErrors(t *testing.T) { t.Fatal("want error on unknown theme") } } + +func TestApplyUpdatesOverlayActive(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + if err := Apply(config.Config{}, "gruvbox"); err != nil { + t.Fatal(err) + } + data, err := os.ReadFile(filepath.Join(home, ".config", "archduino", "overlay.yaml")) + if err != nil { + t.Fatalf("overlay missing: %v", err) + } + if !strings.Contains(string(data), "__active: gruvbox") { + t.Fatalf("overlay missing active theme: %s", data) + } +} + +func TestApplyPreservesOtherOverlayKeys(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + op := filepath.Join(home, ".config", "archduino", "overlay.yaml") + if err := os.MkdirAll(filepath.Dir(op), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(op, []byte("version: 1\nextra_packages:\n - foo\n"), 0o644); err != nil { + t.Fatal(err) + } + + if err := Apply(config.Config{}, "gruvbox"); err != nil { + t.Fatal(err) + } + data, _ := os.ReadFile(op) + if !strings.Contains(string(data), "- foo") { + t.Fatalf("extra_packages lost: %s", data) + } + if !strings.Contains(string(data), "__active: gruvbox") { + t.Fatalf("active theme missing after preserve: %s", data) + } +}