Skip to content

Commit 90cf6bc

Browse files
authored
refactor(experiment): move charm huh implementations to iostreams forms package (#415)
1 parent e1bebf8 commit 90cf6bc

4 files changed

Lines changed: 40 additions & 38 deletions

File tree

.claude/settings.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
{
22
"permissions": {
33
"allow": [
4-
"Bash(go build:*)",
5-
"Bash(go mod tidy:*)",
6-
"Bash(go test:*)",
7-
"Bash(gofmt:*)",
84
"Bash(gh issue view:*)",
95
"Bash(gh label list:*)",
106
"Bash(gh pr checks:*)",
@@ -15,20 +11,25 @@
1511
"Bash(gh pr view:*)",
1612
"Bash(gh search code:*)",
1713
"Bash(git diff:*)",
14+
"Bash(git fetch:*)",
1815
"Bash(git grep:*)",
1916
"Bash(git log:*)",
2017
"Bash(git status:*)",
18+
"Bash(go build:*)",
2119
"Bash(go mod graph:*)",
2220
"Bash(go mod tidy:*)",
21+
"Bash(go mod tidy:*)",
22+
"Bash(go test:*)",
23+
"Bash(gofmt:*)",
2324
"Bash(grep:*)",
2425
"Bash(ls:*)",
25-
"Bash(make build:*)",
2626
"Bash(make build-ci:*)",
27+
"Bash(make build:*)",
2728
"Bash(make lint:*)",
2829
"Bash(make test:*)",
2930
"Bash(tree:*)",
30-
"WebFetch(domain:github.com)",
31-
"WebFetch(domain:docs.slack.dev)"
31+
"WebFetch(domain:docs.slack.dev)",
32+
"WebFetch(domain:github.com)"
3233
]
3334
},
3435
"enabledPlugins": {
Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414

1515
package iostreams
1616

17-
// Charm-based prompt implementations using the huh library.
18-
// These are used when the "huh" experiment is enabled.
17+
// Interactive form-based prompt implementations with Charm's Huh package.
18+
//
19+
// Reference: https://github.com/charmbracelet/huh?tab=readme-ov-file#huh
1920

2021
import (
2122
"context"
@@ -28,7 +29,7 @@ import (
2829
"github.com/slackapi/slack-cli/internal/style"
2930
)
3031

31-
// newForm wraps a field in a huh form, applying the Slack theme when the lipgloss experiment is enabled.
32+
// newForm wraps a field in an interactive form with optional Slack theming.
3233
func newForm(io *IOStreams, field huh.Field) *huh.Form {
3334
form := huh.NewForm(huh.NewGroup(field))
3435
if io != nil && io.config.WithExperimentOn(experiment.Lipgloss) {
@@ -37,7 +38,7 @@ func newForm(io *IOStreams, field huh.Field) *huh.Form {
3738
return form
3839
}
3940

40-
// buildInputForm constructs a huh form for text input prompts.
41+
// buildInputForm constructs an interactive form for text input prompts.
4142
func buildInputForm(io *IOStreams, message string, cfg InputPromptConfig, input *string) *huh.Form {
4243
field := huh.NewInput().
4344
Title(message).
@@ -50,8 +51,8 @@ func buildInputForm(io *IOStreams, message string, cfg InputPromptConfig, input
5051
return newForm(io, field)
5152
}
5253

53-
// charmInputPrompt prompts for text input using a charm huh form
54-
func charmInputPrompt(io *IOStreams, _ context.Context, message string, cfg InputPromptConfig) (string, error) {
54+
// inputForm interactively prompts for text input.
55+
func inputForm(io *IOStreams, _ context.Context, message string, cfg InputPromptConfig) (string, error) {
5556
var input string
5657
err := buildInputForm(io, message, cfg, &input).Run()
5758
if errors.Is(err, huh.ErrUserAborted) {
@@ -62,16 +63,16 @@ func charmInputPrompt(io *IOStreams, _ context.Context, message string, cfg Inpu
6263
return input, nil
6364
}
6465

65-
// buildConfirmForm constructs a huh form for yes/no confirmation prompts.
66+
// buildConfirmForm constructs an interactive form for yes/no confirmation prompts.
6667
func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form {
6768
field := huh.NewConfirm().
6869
Title(message).
6970
Value(choice)
7071
return newForm(io, field)
7172
}
7273

73-
// charmConfirmPrompt prompts for a yes/no confirmation using a charm huh form
74-
func charmConfirmPrompt(io *IOStreams, _ context.Context, message string, defaultValue bool) (bool, error) {
74+
// confirmForm interactively prompts for a yes/no confirmation.
75+
func confirmForm(io *IOStreams, _ context.Context, message string, defaultValue bool) (bool, error) {
7576
var choice = defaultValue
7677
err := buildConfirmForm(io, message, &choice).Run()
7778
if errors.Is(err, huh.ErrUserAborted) {
@@ -82,7 +83,7 @@ func charmConfirmPrompt(io *IOStreams, _ context.Context, message string, defaul
8283
return choice, nil
8384
}
8485

85-
// buildSelectForm constructs a huh form for single-selection prompts.
86+
// buildSelectForm constructs an interactive form for single-selection prompts.
8687
func buildSelectForm(io *IOStreams, msg string, options []string, cfg SelectPromptConfig, selected *string) *huh.Form {
8788
var opts []huh.Option[string]
8889
for _, opt := range options {
@@ -104,8 +105,8 @@ func buildSelectForm(io *IOStreams, msg string, options []string, cfg SelectProm
104105
return newForm(io, field)
105106
}
106107

107-
// charmSelectPrompt prompts the user to select one option using a charm huh form
108-
func charmSelectPrompt(io *IOStreams, _ context.Context, msg string, options []string, cfg SelectPromptConfig) (SelectPromptResponse, error) {
108+
// selectForm interactively prompts the user to select one option.
109+
func selectForm(io *IOStreams, _ context.Context, msg string, options []string, cfg SelectPromptConfig) (SelectPromptResponse, error) {
109110
var selected string
110111
err := buildSelectForm(io, msg, options, cfg, &selected).Run()
111112
if errors.Is(err, huh.ErrUserAborted) {
@@ -118,7 +119,7 @@ func charmSelectPrompt(io *IOStreams, _ context.Context, msg string, options []s
118119
return SelectPromptResponse{Prompt: true, Index: index, Option: selected}, nil
119120
}
120121

121-
// buildPasswordForm constructs a huh form for password (hidden input) prompts.
122+
// buildPasswordForm constructs an interactive form for password (hidden input) prompts.
122123
func buildPasswordForm(io *IOStreams, message string, cfg PasswordPromptConfig, input *string) *huh.Form {
123124
field := huh.NewInput().
124125
Title(message).
@@ -131,8 +132,8 @@ func buildPasswordForm(io *IOStreams, message string, cfg PasswordPromptConfig,
131132
return newForm(io, field)
132133
}
133134

134-
// charmPasswordPrompt prompts for a password (hidden input) using a charm huh form
135-
func charmPasswordPrompt(io *IOStreams, _ context.Context, message string, cfg PasswordPromptConfig) (PasswordPromptResponse, error) {
135+
// passwordForm interactively prompts for a password with hidden input.
136+
func passwordForm(io *IOStreams, _ context.Context, message string, cfg PasswordPromptConfig) (PasswordPromptResponse, error) {
136137
var input string
137138
err := buildPasswordForm(io, message, cfg, &input).Run()
138139
if errors.Is(err, huh.ErrUserAborted) {
@@ -143,7 +144,7 @@ func charmPasswordPrompt(io *IOStreams, _ context.Context, message string, cfg P
143144
return PasswordPromptResponse{Prompt: true, Value: input}, nil
144145
}
145146

146-
// buildMultiSelectForm constructs a huh form for multiple-selection prompts.
147+
// buildMultiSelectForm constructs an interactive form for multiple-selection prompts.
147148
func buildMultiSelectForm(io *IOStreams, message string, options []string, selected *[]string) *huh.Form {
148149
var opts []huh.Option[string]
149150
for _, opt := range options {
@@ -158,8 +159,8 @@ func buildMultiSelectForm(io *IOStreams, message string, options []string, selec
158159
return newForm(io, field)
159160
}
160161

161-
// charmMultiSelectPrompt prompts the user to select multiple options using a charm huh form
162-
func charmMultiSelectPrompt(io *IOStreams, _ context.Context, message string, options []string) ([]string, error) {
162+
// multiSelectForm interactively prompts the user to select multiple options.
163+
func multiSelectForm(io *IOStreams, _ context.Context, message string, options []string) ([]string, error) {
163164
var selected []string
164165
err := buildMultiSelectForm(io, message, options, &selected).Run()
165166
if errors.Is(err, huh.ErrUserAborted) {
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func key(r rune) tea.KeyPressMsg {
3333
return tea.KeyPressMsg{Code: r, Text: string(r)}
3434
}
3535

36-
func TestCharmInput(t *testing.T) {
36+
func TestInputForm(t *testing.T) {
3737
t.Run("renders the title", func(t *testing.T) {
3838
var input string
3939
f := buildInputForm(nil, "Enter your name", InputPromptConfig{}, &input)
@@ -93,7 +93,7 @@ func TestCharmInput(t *testing.T) {
9393
})
9494
}
9595

96-
func TestCharmConfirm(t *testing.T) {
96+
func TestConfirmForm(t *testing.T) {
9797
t.Run("renders the title and buttons", func(t *testing.T) {
9898
choice := false
9999
f := buildConfirmForm(nil, "Are you sure?", &choice)
@@ -128,7 +128,7 @@ func TestCharmConfirm(t *testing.T) {
128128
})
129129
}
130130

131-
func TestCharmSelect(t *testing.T) {
131+
func TestSelectForm(t *testing.T) {
132132
t.Run("renders the title and options", func(t *testing.T) {
133133
var selected string
134134
options := []string{"Foo", "Bar", "Baz"}
@@ -210,7 +210,7 @@ func TestCharmSelect(t *testing.T) {
210210
})
211211
}
212212

213-
func TestCharmPassword(t *testing.T) {
213+
func TestPasswordForm(t *testing.T) {
214214
t.Run("renders the title", func(t *testing.T) {
215215
var input string
216216
f := buildPasswordForm(nil, "Enter password", PasswordPromptConfig{}, &input)
@@ -259,7 +259,7 @@ func TestCharmPassword(t *testing.T) {
259259
})
260260
}
261261

262-
func TestCharmMultiSelect(t *testing.T) {
262+
func TestMultiSelectForm(t *testing.T) {
263263
t.Run("renders the title and options", func(t *testing.T) {
264264
var selected []string
265265
options := []string{"Foo", "Bar", "Baz"}
@@ -305,7 +305,7 @@ func TestCharmMultiSelect(t *testing.T) {
305305
})
306306
}
307307

308-
func TestCharmFormsUseSlackTheme(t *testing.T) {
308+
func TestFormsUseSlackTheme(t *testing.T) {
309309
fsMock := slackdeps.NewFsMock()
310310
osMock := slackdeps.NewOsMock()
311311
osMock.AddDefaultMocks()
@@ -364,7 +364,7 @@ func TestCharmFormsUseSlackTheme(t *testing.T) {
364364
})
365365
}
366366

367-
func TestCharmFormsWithoutLipgloss(t *testing.T) {
367+
func TestFormsWithoutLipgloss(t *testing.T) {
368368
t.Run("multi-select uses default prefix without lipgloss", func(t *testing.T) {
369369
var selected []string
370370
f := buildMultiSelectForm(nil, "Pick", []string{"A", "B"}, &selected)

internal/iostreams/prompts.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
package iostreams
1616

17-
// Prompt type definitions shared between survey and charm implementations.
17+
// Prompts handle flag values and interactive forms for gathering user input.
1818

1919
import (
2020
"context"
@@ -194,7 +194,7 @@ func errInteractivityFlags(cfg PromptConfig) error {
194194
// the message
195195
func (io *IOStreams) ConfirmPrompt(ctx context.Context, message string, defaultValue bool) (bool, error) {
196196
if io.config.WithExperimentOn(experiment.Huh) {
197-
return charmConfirmPrompt(io, ctx, message, defaultValue)
197+
return confirmForm(io, ctx, message, defaultValue)
198198
}
199199
return surveyConfirmPrompt(io, ctx, message, defaultValue)
200200
}
@@ -203,7 +203,7 @@ func (io *IOStreams) ConfirmPrompt(ctx context.Context, message string, defaultV
203203
// optionally be made required
204204
func (io *IOStreams) InputPrompt(ctx context.Context, message string, cfg InputPromptConfig) (string, error) {
205205
if io.config.WithExperimentOn(experiment.Huh) {
206-
return charmInputPrompt(io, ctx, message, cfg)
206+
return inputForm(io, ctx, message, cfg)
207207
}
208208
return surveyInputPrompt(io, ctx, message, cfg)
209209
}
@@ -212,7 +212,7 @@ func (io *IOStreams) InputPrompt(ctx context.Context, message string, cfg InputP
212212
// returns the selected values
213213
func (io *IOStreams) MultiSelectPrompt(ctx context.Context, message string, options []string) ([]string, error) {
214214
if io.config.WithExperimentOn(experiment.Huh) {
215-
return charmMultiSelectPrompt(io, ctx, message, options)
215+
return multiSelectForm(io, ctx, message, options)
216216
}
217217
return surveyMultiSelectPrompt(io, ctx, message, options)
218218
}
@@ -230,7 +230,7 @@ func (io *IOStreams) PasswordPrompt(ctx context.Context, message string, cfg Pas
230230
}
231231

232232
if io.config.WithExperimentOn(experiment.Huh) {
233-
return charmPasswordPrompt(io, ctx, message, cfg)
233+
return passwordForm(io, ctx, message, cfg)
234234
}
235235
return surveyPasswordPrompt(io, ctx, message, cfg)
236236
}
@@ -258,7 +258,7 @@ func (io *IOStreams) SelectPrompt(ctx context.Context, msg string, options []str
258258
}
259259

260260
if io.config.WithExperimentOn(experiment.Huh) {
261-
return charmSelectPrompt(io, ctx, msg, options, cfg)
261+
return selectForm(io, ctx, msg, options, cfg)
262262
}
263263
return surveySelectPrompt(io, ctx, msg, options, cfg)
264264
}

0 commit comments

Comments
 (0)