feat(theme): add dark mode CLI theme support (#911)
Add the ability to force dark or light mode colors for CLI output, overriding the automatic terminal background detection. Changes: - Add CLITheme field to TownSettings for persisting preference - Add GetThemeMode() and HasDarkBackground() to ui package for theme detection with GT_THEME env var override - Add ApplyThemeMode() to explicitly set lipgloss dark background - Add 'gt theme cli' subcommand to view/set CLI theme preference - Initialize theme in CLI startup (persistentPreRun) - Add comprehensive tests for theme mode functionality Usage: - gt theme cli # show current theme - gt theme cli dark # force dark mode - gt theme cli light # force light mode - gt theme cli auto # auto-detect (default) - GT_THEME=dark gt status # per-command override Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -245,3 +245,90 @@ func TestIsAgentMode_CLAUDE_CODE_AnyValue(t *testing.T) {
|
||||
t.Error("IsAgentMode() should return true when CLAUDE_CODE is set to any value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitTheme_EnvOverridesConfig(t *testing.T) {
|
||||
oldGTTheme := os.Getenv("GT_THEME")
|
||||
defer func() {
|
||||
if oldGTTheme != "" {
|
||||
os.Setenv("GT_THEME", oldGTTheme)
|
||||
} else {
|
||||
os.Unsetenv("GT_THEME")
|
||||
}
|
||||
}()
|
||||
|
||||
// Test: env var overrides config
|
||||
os.Setenv("GT_THEME", "dark")
|
||||
InitTheme("light") // config says light
|
||||
if GetThemeMode() != ThemeModeDark {
|
||||
t.Errorf("Expected dark mode from env var, got %s", GetThemeMode())
|
||||
}
|
||||
|
||||
os.Setenv("GT_THEME", "light")
|
||||
InitTheme("dark") // config says dark
|
||||
if GetThemeMode() != ThemeModeLight {
|
||||
t.Errorf("Expected light mode from env var, got %s", GetThemeMode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitTheme_ConfigUsedWhenNoEnv(t *testing.T) {
|
||||
oldGTTheme := os.Getenv("GT_THEME")
|
||||
defer func() {
|
||||
if oldGTTheme != "" {
|
||||
os.Setenv("GT_THEME", oldGTTheme)
|
||||
} else {
|
||||
os.Unsetenv("GT_THEME")
|
||||
}
|
||||
}()
|
||||
|
||||
os.Unsetenv("GT_THEME")
|
||||
|
||||
InitTheme("dark")
|
||||
if GetThemeMode() != ThemeModeDark {
|
||||
t.Errorf("Expected dark mode from config, got %s", GetThemeMode())
|
||||
}
|
||||
|
||||
InitTheme("light")
|
||||
if GetThemeMode() != ThemeModeLight {
|
||||
t.Errorf("Expected light mode from config, got %s", GetThemeMode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitTheme_DefaultsToAuto(t *testing.T) {
|
||||
oldGTTheme := os.Getenv("GT_THEME")
|
||||
defer func() {
|
||||
if oldGTTheme != "" {
|
||||
os.Setenv("GT_THEME", oldGTTheme)
|
||||
} else {
|
||||
os.Unsetenv("GT_THEME")
|
||||
}
|
||||
}()
|
||||
|
||||
os.Unsetenv("GT_THEME")
|
||||
InitTheme("") // no config
|
||||
if GetThemeMode() != ThemeModeAuto {
|
||||
t.Errorf("Expected auto mode as default, got %s", GetThemeMode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasDarkBackground_ForcedModes(t *testing.T) {
|
||||
oldGTTheme := os.Getenv("GT_THEME")
|
||||
defer func() {
|
||||
if oldGTTheme != "" {
|
||||
os.Setenv("GT_THEME", oldGTTheme)
|
||||
} else {
|
||||
os.Unsetenv("GT_THEME")
|
||||
}
|
||||
}()
|
||||
|
||||
os.Setenv("GT_THEME", "dark")
|
||||
InitTheme("")
|
||||
if !HasDarkBackground() {
|
||||
t.Error("Expected HasDarkBackground() to return true when mode is dark")
|
||||
}
|
||||
|
||||
os.Setenv("GT_THEME", "light")
|
||||
InitTheme("")
|
||||
if HasDarkBackground() {
|
||||
t.Error("Expected HasDarkBackground() to return false when mode is light")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user