feat(config): add theme.palette toggle (default on)
- commit
- c0c90a29cbbb7045dcd0f0b642f79a85bba50b4b
- author
- brice · · 2026-07-17 08:08 UTC
- parent
- c646480
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +65 -1
M internal/adapters/config/config.go +7 -0
| @@ -68,6 +68,13 @@ func Parse(r io.Reader) (domain.Config, []domain.Warning, error) { | |||
| 68 | 68 | continue | |
| 69 | 69 | } | |
| 70 | 70 | cfg.Theme = mode | |
| 71 | + | case key == "theme.palette": | |
| 72 | + | on, ok := parseOnOff(value) | |
| 73 | + | if !ok { | |
| 74 | + | warnings = append(warnings, domain.Warning{Line: lineNo, Msg: fmt.Sprintf("invalid theme.palette %q", value)}) | |
| 75 | + | continue | |
| 76 | + | } | |
| 77 | + | cfg.ThemePalette = on | |
| 71 | 78 | case key == "bar.top-right": | |
| 72 | 79 | command, ok := parseBarCommand(value) | |
| 73 | 80 | if !ok { | |
| @@ -68,6 +68,13 @@ func Parse(r io.Reader) (domain.Config, []domain.Warning, error) { | |||||
| 68 | continue | 68 | continue | ||
| 69 | } | 69 | } | ||
| 70 | cfg.Theme = mode | 70 | cfg.Theme = mode | ||
| 71 | + | case key == "theme.palette": | |||
| 72 | + | on, ok := parseOnOff(value) | |||
| 73 | + | if !ok { | |||
| 74 | + | warnings = append(warnings, domain.Warning{Line: lineNo, Msg: fmt.Sprintf("invalid theme.palette %q", value)}) | |||
| 75 | + | continue | |||
| 76 | + | } | |||
| 77 | + | cfg.ThemePalette = on | |||
| 71 | case key == "bar.top-right": | 78 | case key == "bar.top-right": | ||
| 72 | command, ok := parseBarCommand(value) | 79 | command, ok := parseBarCommand(value) | ||
| 73 | if !ok { | 80 | if !ok { | ||
M internal/adapters/config/config_test.go +55 -0
| @@ -332,6 +332,9 @@ func TestParse(t *testing.T) { | |||
| 332 | 332 | t.Run(tt.name, func(t *testing.T) { | |
| 333 | 333 | t.Parallel() | |
| 334 | 334 | ||
| 335 | + | if !tt.want.ThemePalette { | |
| 336 | + | tt.want.ThemePalette = domain.Defaults().ThemePalette | |
| 337 | + | } | |
| 335 | 338 | if tt.want.Bar.Interval == 0 { | |
| 336 | 339 | tt.want.Bar = domain.Defaults().Bar | |
| 337 | 340 | } | |
| @@ -364,6 +367,58 @@ func TestParse(t *testing.T) { | |||
| 364 | 367 | } | |
| 365 | 368 | } | |
| 366 | 369 | ||
| 370 | + | func TestParseThemePalette(t *testing.T) { | |
| 371 | + | t.Parallel() | |
| 372 | + | ||
| 373 | + | tests := []struct { | |
| 374 | + | name string | |
| 375 | + | input string | |
| 376 | + | want bool | |
| 377 | + | wantWarnings []domain.Warning | |
| 378 | + | }{ | |
| 379 | + | { | |
| 380 | + | name: "on enables terminal palette inheritance", | |
| 381 | + | input: "theme.palette = on\n", | |
| 382 | + | want: true, | |
| 383 | + | }, | |
| 384 | + | { | |
| 385 | + | name: "off disables terminal palette inheritance", | |
| 386 | + | input: "theme.palette = off\n", | |
| 387 | + | want: false, | |
| 388 | + | }, | |
| 389 | + | { | |
| 390 | + | name: "invalid value warns once and keeps default", | |
| 391 | + | input: "theme.palette = maybe\n", | |
| 392 | + | want: true, | |
| 393 | + | wantWarnings: []domain.Warning{ | |
| 394 | + | {Line: 1, Msg: "invalid theme.palette \"maybe\""}, | |
| 395 | + | }, | |
| 396 | + | }, | |
| 397 | + | { | |
| 398 | + | name: "absent key keeps default", | |
| 399 | + | input: "theme = dark\n", | |
| 400 | + | want: true, | |
| 401 | + | }, | |
| 402 | + | } | |
| 403 | + | ||
| 404 | + | for _, tt := range tests { | |
| 405 | + | t.Run(tt.name, func(t *testing.T) { | |
| 406 | + | t.Parallel() | |
| 407 | + | ||
| 408 | + | got, warnings, err := Parse(strings.NewReader(tt.input)) | |
| 409 | + | require.NoError(t, err) | |
| 410 | + | require.Equal(t, tt.want, got.ThemePalette) | |
| 411 | + | require.Equal(t, tt.wantWarnings, warnings) | |
| 412 | + | }) | |
| 413 | + | } | |
| 414 | + | } | |
| 415 | + | ||
| 416 | + | func TestDefaultsThemePalette(t *testing.T) { | |
| 417 | + | t.Parallel() | |
| 418 | + | ||
| 419 | + | require.True(t, domain.Defaults().ThemePalette) | |
| 420 | + | } | |
| 421 | + | ||
| 367 | 422 | func TestParseTabsTerminalTitle(t *testing.T) { | |
| 368 | 423 | t.Parallel() | |
| 369 | 424 | ||
| @@ -332,6 +332,9 @@ func TestParse(t *testing.T) { | |||||
| 332 | t.Run(tt.name, func(t *testing.T) { | 332 | t.Run(tt.name, func(t *testing.T) { | ||
| 333 | t.Parallel() | 333 | t.Parallel() | ||
| 334 | 334 | ||||
| 335 | + | if !tt.want.ThemePalette { | |||
| 336 | + | tt.want.ThemePalette = domain.Defaults().ThemePalette | |||
| 337 | + | } | |||
| 335 | if tt.want.Bar.Interval == 0 { | 338 | if tt.want.Bar.Interval == 0 { | ||
| 336 | tt.want.Bar = domain.Defaults().Bar | 339 | tt.want.Bar = domain.Defaults().Bar | ||
| 337 | } | 340 | } | ||
| @@ -364,6 +367,58 @@ func TestParse(t *testing.T) { | |||||
| 364 | } | 367 | } | ||
| 365 | } | 368 | } | ||
| 366 | 369 | ||||
| 370 | + | func TestParseThemePalette(t *testing.T) { | |||
| 371 | + | t.Parallel() | |||
| 372 | + | ||||
| 373 | + | tests := []struct { | |||
| 374 | + | name string | |||
| 375 | + | input string | |||
| 376 | + | want bool | |||
| 377 | + | wantWarnings []domain.Warning | |||
| 378 | + | }{ | |||
| 379 | + | { | |||
| 380 | + | name: "on enables terminal palette inheritance", | |||
| 381 | + | input: "theme.palette = on\n", | |||
| 382 | + | want: true, | |||
| 383 | + | }, | |||
| 384 | + | { | |||
| 385 | + | name: "off disables terminal palette inheritance", | |||
| 386 | + | input: "theme.palette = off\n", | |||
| 387 | + | want: false, | |||
| 388 | + | }, | |||
| 389 | + | { | |||
| 390 | + | name: "invalid value warns once and keeps default", | |||
| 391 | + | input: "theme.palette = maybe\n", | |||
| 392 | + | want: true, | |||
| 393 | + | wantWarnings: []domain.Warning{ | |||
| 394 | + | {Line: 1, Msg: "invalid theme.palette \"maybe\""}, | |||
| 395 | + | }, | |||
| 396 | + | }, | |||
| 397 | + | { | |||
| 398 | + | name: "absent key keeps default", | |||
| 399 | + | input: "theme = dark\n", | |||
| 400 | + | want: true, | |||
| 401 | + | }, | |||
| 402 | + | } | |||
| 403 | + | ||||
| 404 | + | for _, tt := range tests { | |||
| 405 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 406 | + | t.Parallel() | |||
| 407 | + | ||||
| 408 | + | got, warnings, err := Parse(strings.NewReader(tt.input)) | |||
| 409 | + | require.NoError(t, err) | |||
| 410 | + | require.Equal(t, tt.want, got.ThemePalette) | |||
| 411 | + | require.Equal(t, tt.wantWarnings, warnings) | |||
| 412 | + | }) | |||
| 413 | + | } | |||
| 414 | + | } | |||
| 415 | + | ||||
| 416 | + | func TestDefaultsThemePalette(t *testing.T) { | |||
| 417 | + | t.Parallel() | |||
| 418 | + | ||||
| 419 | + | require.True(t, domain.Defaults().ThemePalette) | |||
| 420 | + | } | |||
| 421 | + | ||||
| 367 | func TestParseTabsTerminalTitle(t *testing.T) { | 422 | func TestParseTabsTerminalTitle(t *testing.T) { | ||
| 368 | t.Parallel() | 423 | t.Parallel() | ||
| 369 | 424 | ||||
M internal/domain/config.go +3 -1
| @@ -81,6 +81,7 @@ type TabsConfig struct { | |||
| 81 | 81 | // layer can decide which actions it understands. | |
| 82 | 82 | type Config struct { | |
| 83 | 83 | Theme ThemeMode | |
| 84 | + | ThemePalette bool | |
| 84 | 85 | Bar BarConfig | |
| 85 | 86 | BindingEntries []ConfigEntry | |
| 86 | 87 | Codes map[string]string | |
| @@ -101,7 +102,8 @@ type Warning struct { | |||
| 101 | 102 | // Defaults returns vev's default configuration. | |
| 102 | 103 | func Defaults() Config { | |
| 103 | 104 | return Config{ | |
| 104 | - | Theme: ThemeAuto, | |
| 105 | + | Theme: ThemeAuto, | |
| 106 | + | ThemePalette: true, | |
| 105 | 107 | Bar: BarConfig{ | |
| 106 | 108 | TopRight: "vev-bar-top-right", | |
| 107 | 109 | BottomRight: "vev-bar-bottom-right", | |
| @@ -81,6 +81,7 @@ type TabsConfig struct { | |||||
| 81 | // layer can decide which actions it understands. | 81 | // layer can decide which actions it understands. | ||
| 82 | type Config struct { | 82 | type Config struct { | ||
| 83 | Theme ThemeMode | 83 | Theme ThemeMode | ||
| 84 | + | ThemePalette bool | |||
| 84 | Bar BarConfig | 85 | Bar BarConfig | ||
| 85 | BindingEntries []ConfigEntry | 86 | BindingEntries []ConfigEntry | ||
| 86 | Codes map[string]string | 87 | Codes map[string]string | ||
| @@ -101,7 +102,8 @@ type Warning struct { | |||||
| 101 | // Defaults returns vev's default configuration. | 102 | // Defaults returns vev's default configuration. | ||
| 102 | func Defaults() Config { | 103 | func Defaults() Config { | ||
| 103 | return Config{ | 104 | return Config{ | ||
| 104 | - | Theme: ThemeAuto, | 105 | + | Theme: ThemeAuto, |
| 106 | + | ThemePalette: true, | |||
| 105 | Bar: BarConfig{ | 107 | Bar: BarConfig{ | ||
| 106 | TopRight: "vev-bar-top-right", | 108 | TopRight: "vev-bar-top-right", | ||
| 107 | BottomRight: "vev-bar-bottom-right", | 109 | BottomRight: "vev-bar-bottom-right", | ||