77 "charm.land/lipgloss/v2"
88 "github.com/spf13/cobra"
99 "github.com/verda-cloud/verdagostack/pkg/tui/bubbletea"
10+ "github.com/verda-cloud/verdagostack/pkg/tui/wizard"
1011
1112 cmdutil "github/verda-cloud/verda-cli/internal/verda-cli/cmd/util"
1213 "github/verda-cloud/verda-cli/internal/verda-cli/options"
@@ -18,88 +19,79 @@ func NewCmdTheme(f cmdutil.Factory, ioStreams cmdutil.IOStreams) *cobra.Command
1819 Use : "theme [name]" ,
1920 Short : "View or change the CLI color theme" ,
2021 Long : cmdutil .LongDesc (`
21- View the current theme, list available themes, or set a new theme.
22+ View and change the CLI color theme.
2223
23- Without arguments, shows the current theme and lists available options .
24- With a theme name, sets it as the active theme .
24+ Without arguments, opens an interactive theme selector .
25+ With a theme name, sets it directly .
2526 ` ),
2627 Example : cmdutil .Examples (`
27- # Show current theme and list available
28+ # Interactive selection
2829 verda settings theme
2930
30- # Set a theme
31+ # Set a theme directly
3132 verda settings theme dracula
32-
33- # Interactive selection
34- verda settings theme --select
3533 ` ),
36- Args : cobra .MaximumNArgs (1 ),
34+ Args : cobra .MaximumNArgs (1 ),
35+ ValidArgsFunction : completeThemeNames ,
3736 RunE : func (cmd * cobra.Command , args []string ) error {
3837 if len (args ) == 1 {
39- return setTheme (f , ioStreams , args [0 ])
40- }
41- selectFlag , _ := cmd .Flags ().GetBool ("select" )
42- if selectFlag {
43- return selectTheme (cmd , f , ioStreams )
38+ return setTheme (ioStreams , args [0 ])
4439 }
45- return showTheme ( ioStreams )
40+ return selectThemeWizard ( cmd , f , ioStreams )
4641 },
4742 }
4843
49- cmd .Flags ().BoolP ("select" , "s" , false , "Interactively select a theme" )
50-
5144 return cmd
5245}
5346
54- func showTheme ( ioStreams cmdutil.IOStreams ) error {
47+ func selectThemeWizard ( cmd * cobra. Command , f cmdutil. Factory , ioStreams cmdutil.IOStreams ) error {
5548 current := bubbletea .GetThemeName ()
56- names := bubbletea .ThemeNames ()
57- slices .Sort (names )
58-
59- bold := lipgloss .NewStyle ().Bold (true )
60- dim := lipgloss .NewStyle ().Foreground (lipgloss .Color ("8" ))
49+ var selected string
6150
62- _ , _ = fmt .Fprintf (ioStreams .Out , "\n %s %s\n \n " , bold .Render ("Current theme:" ), current )
63-
64- for _ , name := range names {
65- theme := bubbletea .Themes [name ]
66- marker := " "
67- if name == current {
68- marker = "* "
69- }
70- preview := renderThemePreview (name , theme )
71- _ , _ = fmt .Fprintf (ioStreams .Out , " %s%s\n " , marker , preview )
72- }
73-
74- _ , _ = fmt .Fprintf (ioStreams .Out , "\n %s\n \n " , dim .Render ("Use \" verda settings theme <name>\" or \" verda settings theme --select\" " ))
75- return nil
76- }
77-
78- func selectTheme (cmd * cobra.Command , f cmdutil.Factory , ioStreams cmdutil.IOStreams ) error {
79- current := bubbletea .GetThemeName ()
8051 names := bubbletea .ThemeNames ()
8152 slices .Sort (names )
82-
83- labels := make ([]string , len (names ))
53+ choices := make ([]wizard.Choice , len (names ))
8454 for i , name := range names {
85- theme := bubbletea .Themes [name ]
86- label := renderThemePreview (name , theme )
55+ t := bubbletea .Themes [name ]
56+ label := renderThemePreview (name , & t )
8757 if name == current {
8858 label += " (current)"
8959 }
90- labels [i ] = label
60+ choices [i ] = wizard.Choice {Label : label , Value : name }
61+ }
62+
63+ flow := & wizard.Flow {
64+ Name : "theme-select" ,
65+ Layout : []wizard.ViewDef {
66+ {ID : "hints" , View : wizard .NewHintBarView (wizard .WithHintStyle (bubbletea .HintStyle ()))},
67+ },
68+ Steps : []wizard.Step {
69+ {
70+ Name : "theme" ,
71+ Description : "Select theme" ,
72+ Prompt : wizard .SelectPrompt ,
73+ Loader : wizard .StaticChoices (choices ... ),
74+ Default : func (_ map [string ]any ) any { return current },
75+ Setter : func (v any ) { selected = v .(string ) },
76+ IsSet : func () bool { return selected != "" },
77+ Value : func () any { return selected },
78+ },
79+ },
9180 }
9281
93- prompter := f .Prompter ()
94- idx , err := prompter .Select (cmd .Context (), "Select theme" , labels )
95- if err != nil {
96- return nil //nolint:nilerr // User pressed Esc/Ctrl+C during prompt.
82+ engine := wizard .NewEngine (f .Prompter (), f .Status (), wizard .WithOutput (ioStreams .ErrOut ))
83+ if err := engine .Run (cmd .Context (), flow ); err != nil {
84+ return nil //nolint:nilerr // User pressed Esc/Ctrl+C.
9785 }
9886
99- return setTheme (f , ioStreams , names [idx ])
87+ if selected == "" || selected == current {
88+ return nil
89+ }
90+
91+ return setTheme (ioStreams , selected )
10092}
10193
102- func setTheme (f cmdutil. Factory , ioStreams cmdutil.IOStreams , name string ) error {
94+ func setTheme (ioStreams cmdutil.IOStreams , name string ) error {
10395 if ! bubbletea .SetThemeByName (name ) {
10496 names := bubbletea .ThemeNames ()
10597 slices .Sort (names )
@@ -114,16 +106,34 @@ func setTheme(f cmdutil.Factory, ioStreams cmdutil.IOStreams, name string) error
114106 return nil
115107}
116108
117- func renderThemePreview (name string , theme bubbletea.Theme ) string {
109+ func renderThemePreview (name string , theme * bubbletea.Theme ) string {
110+ if theme .NoColor {
111+ bold := lipgloss .NewStyle ().Bold (true )
112+ faint := lipgloss .NewStyle ().Faint (true )
113+ rev := lipgloss .NewStyle ().Reverse (true )
114+ uline := lipgloss .NewStyle ().Bold (true ).Underline (true )
115+ return fmt .Sprintf ("%-16s %s %s %s %s" ,
116+ name ,
117+ bold .Render ("bold" ),
118+ faint .Render ("faint" ),
119+ rev .Render ("reverse" ),
120+ uline .Render ("error" ))
121+ }
122+
118123 accent := lipgloss .NewStyle ().Foreground (theme .Accent )
119124 success := lipgloss .NewStyle ().Foreground (theme .Success )
120125 errStyle := lipgloss .NewStyle ().Foreground (theme .Error )
121126 dim := lipgloss .NewStyle ().Foreground (theme .Dim )
122127
123- return fmt .Sprintf ("%-12s %s %s %s %s" ,
128+ return fmt .Sprintf ("%-16s %s %s %s %s" ,
124129 name ,
125130 accent .Render ("accent" ),
126131 success .Render ("success" ),
127132 errStyle .Render ("error" ),
128133 dim .Render ("dim" ))
129134}
135+
136+ func completeThemeNames (_ * cobra.Command , _ []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
137+ names := bubbletea .ThemeNames ()
138+ return names , cobra .ShellCompDirectiveNoFileComp
139+ }
0 commit comments