From 207a38e2368ad94d1f12f5cc170dafea4d64e211 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 10:37:37 +0000 Subject: [PATCH] fix(cli): improve prompt recovery hints Co-authored-by: Virgil --- pkg/cli/prompt.go | 10 ++++++---- pkg/cli/utils.go | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/pkg/cli/prompt.go b/pkg/cli/prompt.go index 8f9d8d7..f95bec1 100644 --- a/pkg/cli/prompt.go +++ b/pkg/cli/prompt.go @@ -71,9 +71,10 @@ func Select(label string, options []string) (string, error) { return "", err } - n, err := strconv.Atoi(strings.TrimSpace(input)) + trimmed := strings.TrimSpace(input) + n, err := strconv.Atoi(trimmed) if err != nil || n < 1 || n > len(options) { - return "", fmt.Errorf("invalid selection: choose a number between 1 and %d", len(options)) + return "", fmt.Errorf("invalid selection %q: choose a number between 1 and %d", trimmed, len(options)) } return options[n-1], nil } @@ -99,9 +100,10 @@ func MultiSelect(label string, options []string) ([]string, error) { return nil, err } - selected, parseErr := parseMultiSelection(strings.TrimSpace(input), len(options)) + trimmed := strings.TrimSpace(input) + selected, parseErr := parseMultiSelection(trimmed, len(options)) if parseErr != nil { - return nil, fmt.Errorf("invalid selection: %w", parseErr) + return nil, fmt.Errorf("invalid selection %q: %w", trimmed, parseErr) } selectedOptions := make([]string, 0, len(selected)) diff --git a/pkg/cli/utils.go b/pkg/cli/utils.go index a5cc3fb..bd2151f 100644 --- a/pkg/cli/utils.go +++ b/pkg/cli/utils.go @@ -137,7 +137,7 @@ func Confirm(prompt string, opts ...ConfirmOption) bool { // Handle empty response if response == "" { if readErr == nil && cfg.required { - fmt.Println("Please enter 'y' or 'n'") + fmt.Println("Please enter y or n, then press Enter.") continue } if cfg.required { @@ -156,7 +156,7 @@ func Confirm(prompt string, opts ...ConfirmOption) bool { // Invalid response if cfg.required { - fmt.Println("Please enter 'y' or 'n'") + fmt.Println("Please enter y or n, then press Enter.") continue } @@ -250,7 +250,7 @@ func Question(prompt string, opts ...QuestionOption) string { // Handle empty response if response == "" { if cfg.required { - fmt.Println("Please enter a value") + fmt.Println("Please enter a value, then press Enter.") continue } response = cfg.defaultValue @@ -375,10 +375,10 @@ func Choose[T any](prompt string, items []T, opts ...ChooseOption[T]) T { return items[idx] } if cfg.defaultN >= 0 { - fmt.Printf("Default selection is not available in the current list\n") + fmt.Printf("Default selection is not available in the current list. Narrow the list or choose another number.\n") continue } - fmt.Printf("Please enter a number between 1 and %d\n", len(visible)) + fmt.Printf("Please enter a number between 1 and %d.\n", len(visible)) continue } @@ -387,21 +387,21 @@ func Choose[T any](prompt string, items []T, opts ...ChooseOption[T]) T { if n >= 1 && n <= len(visible) { return items[visible[n-1]] } - fmt.Printf("Please enter a number between 1 and %d\n", len(visible)) + fmt.Printf("Please enter a number between 1 and %d.\n", len(visible)) continue } if cfg.filter { nextVisible := filterVisible(items, visible, response, cfg.displayFn) if len(nextVisible) == 0 { - fmt.Printf("No matches for %q\n", response) + fmt.Printf("No matches for %q. Try a shorter search term or clear the filter.\n", response) continue } visible = nextVisible continue } - fmt.Printf("Please enter a number between 1 and %d\n", len(visible)) + fmt.Printf("Please enter a number between 1 and %d.\n", len(visible)) } } @@ -462,7 +462,7 @@ func ChooseMulti[T any](prompt string, items []T, opts ...ChooseOption[T]) []T { return []T{items[idx]} } if cfg.defaultN >= 0 { - fmt.Printf("Default selection is not available in the current list\n") + fmt.Printf("Default selection is not available in the current list. Narrow the list or choose another number.\n") continue } return nil @@ -474,13 +474,13 @@ func ChooseMulti[T any](prompt string, items []T, opts ...ChooseOption[T]) []T { if cfg.filter && !looksLikeMultiSelectionInput(response) { nextVisible := filterVisible(items, visible, response, cfg.displayFn) if len(nextVisible) == 0 { - fmt.Printf("No matches for %q\n", response) + fmt.Printf("No matches for %q. Try a shorter search term or clear the filter.\n", response) continue } visible = nextVisible continue } - fmt.Printf("Invalid selection: %v\n", err) + fmt.Printf("Invalid selection %q: enter numbers like 1 3 or 1-3.\n", response) continue } -- 2.45.3