From 87513483e82a4e540f8f50caf6a739373b498674 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 10:28:43 +0000 Subject: [PATCH] fix(cli): remove implicit chooser defaults Co-Authored-By: Virgil --- pkg/cli/prompt_test.go | 24 ++++++++++++++++++++++++ pkg/cli/utils.go | 19 ++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/pkg/cli/prompt_test.go b/pkg/cli/prompt_test.go index b1b9bb5..c9684e3 100644 --- a/pkg/cli/prompt_test.go +++ b/pkg/cli/prompt_test.go @@ -173,6 +173,30 @@ func TestChoose_Good_DefaultIndex(t *testing.T) { assert.Equal(t, "b", val) } +func TestChoose_Good_EmptyRepromptsWithoutDefault(t *testing.T) { + SetStdin(strings.NewReader("\n2\n")) + defer SetStdin(nil) + + val := Choose("Pick", []string{"a", "b", "c"}) + assert.Equal(t, "b", val) +} + +func TestChoose_Bad_EOFWithoutDefaultReturnsZeroValue(t *testing.T) { + SetStdin(strings.NewReader("")) + defer SetStdin(nil) + + val := Choose("Pick", []string{"a", "b", "c"}) + assert.Empty(t, val) +} + +func TestChooseMulti_Good_EmptyWithoutDefaultReturnsNone(t *testing.T) { + SetStdin(strings.NewReader("\n")) + defer SetStdin(nil) + + vals := ChooseMulti("Pick", []string{"a", "b", "c"}) + assert.Empty(t, vals) +} + func TestChoose_Good_Filter(t *testing.T) { SetStdin(strings.NewReader("ap\n2\n")) defer SetStdin(nil) diff --git a/pkg/cli/utils.go b/pkg/cli/utils.go index 85c4a06..1fca45e 100644 --- a/pkg/cli/utils.go +++ b/pkg/cli/utils.go @@ -337,6 +337,7 @@ func Choose[T any](prompt string, items []T, opts ...ChooseOption[T]) T { cfg := &chooseConfig[T]{ displayFn: func(item T) string { return fmt.Sprint(item) }, + defaultN: -1, } for _, opt := range opts { opt(cfg) @@ -358,12 +359,23 @@ func Choose[T any](prompt string, items []T, opts ...ChooseOption[T]) T { } else { fmt.Printf("Enter number [1-%d]: ", len(visible)) } - response, _ := reader.ReadString('\n') + response, err := reader.ReadString('\n') response = strings.TrimSpace(response) - // Empty response uses default. + if err != nil && response == "" { + if cfg.defaultN >= 0 { + return items[defaultVisibleIndex(visible, cfg.defaultN)] + } + var zero T + return zero + } + if response == "" { - return items[defaultVisibleIndex(visible, cfg.defaultN)] + if cfg.defaultN >= 0 { + return items[defaultVisibleIndex(visible, cfg.defaultN)] + } + fmt.Printf("Please enter a number between 1 and %d\n", len(visible)) + continue } var n int @@ -415,6 +427,7 @@ func ChooseMulti[T any](prompt string, items []T, opts ...ChooseOption[T]) []T { cfg := &chooseConfig[T]{ displayFn: func(item T) string { return fmt.Sprint(item) }, + defaultN: -1, } for _, opt := range opts { opt(cfg) -- 2.45.3