From 9ea1dfe406bcf26321fb40d5b1f28cff8507c877 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Wed, 27 May 2026 15:48:15 -0600 Subject: [PATCH 1/7] fix: confusing y/n confirm prompt --- internal/iostreams/forms.go | 6 +++++- internal/iostreams/forms_test.go | 14 +++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index 532a521b..42e2228d 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -82,8 +82,12 @@ func inputForm(io *IOStreams, _ context.Context, message string, cfg InputPrompt // buildConfirmForm constructs an interactive form for yes/no confirmation prompts. func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { - field := huh.NewConfirm(). + field := huh.NewSelect[bool](). Title(message). + Options( + huh.NewOption("Yes", true), + huh.NewOption("No", false), + ). Value(choice) return newForm(io, field) } diff --git a/internal/iostreams/forms_test.go b/internal/iostreams/forms_test.go index 721d4e6c..ed6627a4 100644 --- a/internal/iostreams/forms_test.go +++ b/internal/iostreams/forms_test.go @@ -113,17 +113,17 @@ func TestConfirmForm(t *testing.T) { assert.True(t, choice) }) - t.Run("toggle changes value", func(t *testing.T) { + t.Run("arrow keys change selection", func(t *testing.T) { choice := false f := buildConfirmForm(nil, "Continue?", &choice) f.Update(f.Init()) - // Toggle to Yes - f.Update(tea.KeyPressMsg{Code: tea.KeyLeft}) + // Move up to Yes + f.Update(tea.KeyPressMsg{Code: tea.KeyUp}) assert.True(t, choice) - // Toggle back to No - f.Update(tea.KeyPressMsg{Code: tea.KeyRight}) + // Move back down to No + f.Update(tea.KeyPressMsg{Code: tea.KeyDown}) assert.False(t, choice) }) } @@ -450,12 +450,12 @@ func TestFormsAccessible(t *testing.T) { assert.Contains(t, out.String(), "Pick one (press Enter for 1)") }) - t.Run("confirm form accepts yes/no input", func(t *testing.T) { + t.Run("confirm form accepts numbered input", func(t *testing.T) { var choice bool f := buildConfirmForm(io, "Continue?", &choice) var out strings.Builder - err := f.WithOutput(&out).WithInput(strings.NewReader("y\n")).Run() + err := f.WithOutput(&out).WithInput(strings.NewReader("1\n")).Run() assert.NoError(t, err) assert.True(t, choice) From 9a8cbee8cb9edf7086c13defa9916a3ac4b37595 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Thu, 28 May 2026 09:41:20 -0600 Subject: [PATCH 2/7] fix: make default value top option --- internal/iostreams/forms.go | 2 +- internal/iostreams/forms_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index 42e2228d..c0ab5cb4 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -85,8 +85,8 @@ func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { field := huh.NewSelect[bool](). Title(message). Options( - huh.NewOption("Yes", true), huh.NewOption("No", false), + huh.NewOption("Yes", true), ). Value(choice) return newForm(io, field) diff --git a/internal/iostreams/forms_test.go b/internal/iostreams/forms_test.go index ed6627a4..3bd30f89 100644 --- a/internal/iostreams/forms_test.go +++ b/internal/iostreams/forms_test.go @@ -118,12 +118,12 @@ func TestConfirmForm(t *testing.T) { f := buildConfirmForm(nil, "Continue?", &choice) f.Update(f.Init()) - // Move up to Yes - f.Update(tea.KeyPressMsg{Code: tea.KeyUp}) + // Move down to Yes + f.Update(tea.KeyPressMsg{Code: tea.KeyDown}) assert.True(t, choice) - // Move back down to No - f.Update(tea.KeyPressMsg{Code: tea.KeyDown}) + // Move back up to No + f.Update(tea.KeyPressMsg{Code: tea.KeyUp}) assert.False(t, choice) }) } @@ -455,7 +455,7 @@ func TestFormsAccessible(t *testing.T) { f := buildConfirmForm(io, "Continue?", &choice) var out strings.Builder - err := f.WithOutput(&out).WithInput(strings.NewReader("1\n")).Run() + err := f.WithOutput(&out).WithInput(strings.NewReader("2\n")).Run() assert.NoError(t, err) assert.True(t, choice) From 199785bcde316e24ed7fcd1bd05ade430f0e8469 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Fri, 29 May 2026 14:29:54 -0600 Subject: [PATCH 3/7] remove defaultvalue --- internal/iostreams/forms.go | 6 +++--- internal/iostreams/forms_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index c0ab5cb4..66b35d5f 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -85,16 +85,16 @@ func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { field := huh.NewSelect[bool](). Title(message). Options( - huh.NewOption("No", false), huh.NewOption("Yes", true), + huh.NewOption("No", false), ). Value(choice) return newForm(io, field) } // confirmForm interactively prompts for a yes/no confirmation. -func confirmForm(io *IOStreams, _ context.Context, message string, defaultValue bool) (bool, error) { - var choice = defaultValue +func confirmForm(io *IOStreams, _ context.Context, message string, _ bool) (bool, error) { + var choice = true err := buildConfirmForm(io, message, &choice).Run() if errors.Is(err, huh.ErrUserAborted) { return false, slackerror.New(slackerror.ErrProcessInterrupted) diff --git a/internal/iostreams/forms_test.go b/internal/iostreams/forms_test.go index 3bd30f89..eb3ea821 100644 --- a/internal/iostreams/forms_test.go +++ b/internal/iostreams/forms_test.go @@ -455,7 +455,7 @@ func TestFormsAccessible(t *testing.T) { f := buildConfirmForm(io, "Continue?", &choice) var out strings.Builder - err := f.WithOutput(&out).WithInput(strings.NewReader("2\n")).Run() + err := f.WithOutput(&out).WithInput(strings.NewReader("1\n")).Run() assert.NoError(t, err) assert.True(t, choice) From 4e52cbdbe5a1a7bfed8aca2e57a60bf48fb6963a Mon Sep 17 00:00:00 2001 From: Ale Mercado <104795114+srtaalej@users.noreply.github.com> Date: Mon, 1 Jun 2026 23:14:43 -0500 Subject: [PATCH 4/7] Update internal/iostreams/forms.go Co-authored-by: Eden Zimbelman --- internal/iostreams/forms.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index 66b35d5f..fdbe1177 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -93,7 +93,7 @@ func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { } // confirmForm interactively prompts for a yes/no confirmation. -func confirmForm(io *IOStreams, _ context.Context, message string, _ bool) (bool, error) { +func confirmForm(io *IOStreams, _ context.Context, message string) (bool, error) { var choice = true err := buildConfirmForm(io, message, &choice).Run() if errors.Is(err, huh.ErrUserAborted) { From 11f086b341d9521980c0c2b9109acdf8f720beab Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Mon, 1 Jun 2026 23:52:46 -0500 Subject: [PATCH 5/7] Revert "Update internal/iostreams/forms.go" This reverts commit 4e52cbdbe5a1a7bfed8aca2e57a60bf48fb6963a. --- internal/iostreams/forms.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index fdbe1177..66b35d5f 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -93,7 +93,7 @@ func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { } // confirmForm interactively prompts for a yes/no confirmation. -func confirmForm(io *IOStreams, _ context.Context, message string) (bool, error) { +func confirmForm(io *IOStreams, _ context.Context, message string, _ bool) (bool, error) { var choice = true err := buildConfirmForm(io, message, &choice).Run() if errors.Is(err, huh.ErrUserAborted) { From e96f3997aef74f7bb140aa0726e719555549074b Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Tue, 2 Jun 2026 11:36:58 -0500 Subject: [PATCH 6/7] Reapply "Update internal/iostreams/forms.go" This reverts commit 11f086b341d9521980c0c2b9109acdf8f720beab. --- internal/iostreams/forms.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index 66b35d5f..fdbe1177 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -93,7 +93,7 @@ func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { } // confirmForm interactively prompts for a yes/no confirmation. -func confirmForm(io *IOStreams, _ context.Context, message string, _ bool) (bool, error) { +func confirmForm(io *IOStreams, _ context.Context, message string) (bool, error) { var choice = true err := buildConfirmForm(io, message, &choice).Run() if errors.Is(err, huh.ErrUserAborted) { From 3e78f649a538337011261f48e69a430282cdb4b6 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Tue, 2 Jun 2026 11:54:09 -0500 Subject: [PATCH 7/7] fix: respect defaultValue in confirmForm --- internal/iostreams/forms.go | 4 ++-- internal/iostreams/forms_test.go | 24 +++++++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/internal/iostreams/forms.go b/internal/iostreams/forms.go index fdbe1177..42e2228d 100644 --- a/internal/iostreams/forms.go +++ b/internal/iostreams/forms.go @@ -93,8 +93,8 @@ func buildConfirmForm(io *IOStreams, message string, choice *bool) *huh.Form { } // confirmForm interactively prompts for a yes/no confirmation. -func confirmForm(io *IOStreams, _ context.Context, message string) (bool, error) { - var choice = true +func confirmForm(io *IOStreams, _ context.Context, message string, defaultValue bool) (bool, error) { + var choice = defaultValue err := buildConfirmForm(io, message, &choice).Run() if errors.Is(err, huh.ErrUserAborted) { return false, slackerror.New(slackerror.ErrProcessInterrupted) diff --git a/internal/iostreams/forms_test.go b/internal/iostreams/forms_test.go index eb3ea821..e42f80df 100644 --- a/internal/iostreams/forms_test.go +++ b/internal/iostreams/forms_test.go @@ -105,26 +105,36 @@ func TestConfirmForm(t *testing.T) { assert.Contains(t, view, "No") }) - t.Run("default value is respected", func(t *testing.T) { + t.Run("default true starts on Yes", func(t *testing.T) { choice := true f := buildConfirmForm(nil, "Continue?", &choice) f.Update(f.Init()) - assert.True(t, choice) + view := ansi.Strip(f.View()) + assert.Contains(t, view, style.Chevron()+" Yes") }) - t.Run("arrow keys change selection", func(t *testing.T) { + t.Run("default false starts on No", func(t *testing.T) { choice := false f := buildConfirmForm(nil, "Continue?", &choice) f.Update(f.Init()) - // Move down to Yes + view := ansi.Strip(f.View()) + assert.Contains(t, view, style.Chevron()+" No") + }) + + t.Run("arrow keys change selection", func(t *testing.T) { + choice := true + f := buildConfirmForm(nil, "Continue?", &choice) + f.Update(f.Init()) + + // Move down to No f.Update(tea.KeyPressMsg{Code: tea.KeyDown}) - assert.True(t, choice) + assert.False(t, choice) - // Move back up to No + // Move back up to Yes f.Update(tea.KeyPressMsg{Code: tea.KeyUp}) - assert.False(t, choice) + assert.True(t, choice) }) }