Skip to content

Commit d10e094

Browse files
hi-leiclaude
andcommitted
feat: upgrade verdagostack to v1.1.2, add theme-aware hints and interactive theme selector
- Upgrade verdagostack to v1.1.2 (hint bar theming, mono themes, text input hints) - Wire theme hint style to HintBarView in vm create and auth login wizards - Replace static theme list with interactive wizard selector for `verda settings theme` - Add mono theme preview support (bold/faint/reverse) in theme list - Add shell tab completion for theme names Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f6217c8 commit d10e094

5 files changed

Lines changed: 73 additions & 60 deletions

File tree

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ require (
99
github.com/spf13/pflag v1.0.10
1010
github.com/spf13/viper v1.21.0
1111
github.com/verda-cloud/verdacloud-sdk-go v1.4.2
12-
github.com/verda-cloud/verdagostack v1.1.1
12+
github.com/verda-cloud/verdagostack v1.1.2
1313
go.yaml.in/yaml/v3 v3.0.4
14-
gopkg.in/ini.v1 v1.67.1
1514
)
1615

16+
require gopkg.in/ini.v1 v1.67.1
17+
1718
require (
1819
charm.land/bubbles/v2 v2.1.0 // indirect
1920
charm.land/bubbletea/v2 v2.0.2 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
9898
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
9999
github.com/verda-cloud/verdacloud-sdk-go v1.4.2 h1:oVb8fHVQOY+YPuuMYMee9gYCkPTwAw01LmkqxM21T/Y=
100100
github.com/verda-cloud/verdacloud-sdk-go v1.4.2/go.mod h1:pmlpiCL9fTSikZ3qWLJPpHOG0E8PKkQVUX5s4Z+SktY=
101-
github.com/verda-cloud/verdagostack v1.1.1 h1:pHWouGPuND5FRuaf/IURie1jjs2fj9eY9gT2fUFCMa8=
102-
github.com/verda-cloud/verdagostack v1.1.1/go.mod h1:9uKLNxvH7JRkHj2sxZc4TI5O/JbbveCrLkOkekoY/sA=
101+
github.com/verda-cloud/verdagostack v1.1.2 h1:J/TL9CPDnbLuUgd5Lj0ppNmTG1iXuMq4L9gT+H5vwrI=
102+
github.com/verda-cloud/verdagostack v1.1.2/go.mod h1:9uKLNxvH7JRkHj2sxZc4TI5O/JbbveCrLkOkekoY/sA=
103103
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
104104
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
105105
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=

internal/verda-cli/cmd/auth/wizard.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"strings"
66

7+
"github.com/verda-cloud/verdagostack/pkg/tui/bubbletea"
78
"github.com/verda-cloud/verdagostack/pkg/tui/wizard"
89
)
910

@@ -20,7 +21,7 @@ func buildLoginFlow(opts *loginOptions) *wizard.Flow {
2021
Name: "auth-login",
2122
Layout: []wizard.ViewDef{
2223
{ID: "progress", View: wizard.NewProgressView(wizard.WithProgressPercent())},
23-
{ID: "hints", View: wizard.NewHintBarView()},
24+
{ID: "hints", View: wizard.NewHintBarView(wizard.WithHintStyle(bubbletea.HintStyle()))},
2425
},
2526
Steps: []wizard.Step{
2627
loginStepProfile(opts),

internal/verda-cli/cmd/settings/theme.go

Lines changed: 64 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
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+
}

internal/verda-cli/cmd/vm/wizard.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"charm.land/lipgloss/v2"
1414
"github.com/verda-cloud/verdacloud-sdk-go/pkg/verda"
1515
"github.com/verda-cloud/verdagostack/pkg/tui"
16+
"github.com/verda-cloud/verdagostack/pkg/tui/bubbletea"
1617
"github.com/verda-cloud/verdagostack/pkg/tui/wizard"
1718

1819
cmdutil "github/verda-cloud/verda-cli/internal/verda-cli/cmd/util"
@@ -80,7 +81,7 @@ func buildCreateFlow(getClient clientFunc, opts *createOptions) *wizard.Flow {
8081
Name: "vm-create",
8182
Layout: []wizard.ViewDef{
8283
{ID: "progress", View: wizard.NewProgressView(wizard.WithProgressPercent())},
83-
{ID: "hints", View: wizard.NewHintBarView()},
84+
{ID: "hints", View: wizard.NewHintBarView(wizard.WithHintStyle(bubbletea.HintStyle()))},
8485
},
8586
Steps: []wizard.Step{
8687
stepBillingType(opts),

0 commit comments

Comments
 (0)