Files
Archduino/internal/tui/state.go
MDietermann 4f7411ca95 refactor: retire tui.BuiltinThemes in favor of theming.List
Make internal/theming.List the single source of truth for themes:

- Drop tui.BuiltinThemes, tui.ThemeByID, and the NvChadTheme field on
  tui.Theme. tui.Theme is now a thin {ID, Name} display value.
- Wizard populates its dropdown from theming.List() and uses
  DisplayName for the label.
- neovim.resolvedTheme uses theming.Get (with theming.List()[0] as a
  fallback) instead of a caller-supplied []tui.Theme slice.
- neovim.New signature loses the themes []tui.Theme parameter; update
  cmd/archduino/main.go and all neovim tests to match.

Break the resulting neovim→theming import cycle (theming previously
imported neovim for WriteChadrc) by inverting the dependency:
theming exposes a ChadrcWriter function hook, and neovim registers
its WriteChadrc into it via package init. The theming test stubs
ChadrcWriter directly to exercise the chadrc-rewrite branch without
pulling neovim in and re-creating the cycle.

Delete the now-obsolete TestBuiltinThemesCarryNvChadName / TestThemeByID*
tests in internal/tui/state_test.go — their coverage lives in the
theming package's own tests.
2026-04-14 13:35:10 +02:00

82 lines
2.2 KiB
Go

package tui
import (
"sort"
"github.com/MDietermann/ArduinoArchSetup/internal/config"
"github.com/MDietermann/ArduinoArchSetup/internal/module"
"github.com/MDietermann/ArduinoArchSetup/internal/theming"
)
// Theme is a named colorscheme presented in the wizard. It is a thin
// display value for the dropdown; the authoritative theme catalogue lives
// in the theming package (theming.List / theming.Get).
type Theme struct {
ID string
Name string
}
// ModuleChoice is one row in the module selector.
type ModuleChoice struct {
ID string
Name string
Description string
Selected bool
}
// WizardState is the payload the wizard fills in and the dashboard reads.
type WizardState struct {
ThemeID string
Modules []ModuleChoice
Parallelism int // advanced; reserved for a future concurrent engine
HaltOnError bool // advanced
Confirmed bool // true once the user hits Confirm on the last screen
}
// NewWizardState builds an initial state from the running config and the
// registered modules. Pre-ticks all modules except those disabled in the
// overlay, defaults the theme to the first built-in theme.
func NewWizardState(cfg config.Config, reg *module.Registry) WizardState {
disabled := map[string]bool{}
for _, id := range cfg.DisabledModules {
disabled[id] = true
}
mods := reg.All()
choices := make([]ModuleChoice, 0, len(mods))
for _, m := range mods {
meta := m.Meta()
choices = append(choices, ModuleChoice{
ID: meta.ID,
Name: meta.Name,
Description: meta.Description,
Selected: !disabled[meta.ID],
})
}
sort.Slice(choices, func(i, j int) bool { return choices[i].ID < choices[j].ID })
var theme string
if list := theming.List(); len(list) > 0 {
theme = list[0].ID
}
if override, ok := cfg.ThemeOverrides["__active"]; ok && override != "" {
theme = override
}
return WizardState{
ThemeID: theme,
Modules: choices,
Parallelism: 1,
}
}
// SelectedIDs returns only the checked module IDs.
func (s WizardState) SelectedIDs() []string {
out := make([]string, 0, len(s.Modules))
for _, m := range s.Modules {
if m.Selected {
out = append(out, m.ID)
}
}
return out
}