diff --git a/pkg/cli/prompt_test.go b/pkg/cli/prompt_test.go index 926d969..80d3467 100644 --- a/pkg/cli/prompt_test.go +++ b/pkg/cli/prompt_test.go @@ -94,6 +94,13 @@ func TestConfirm_Bad_EOFUsesDefault(t *testing.T) { assert.True(t, Confirm("Proceed?", DefaultYes(), Required())) } +func TestConfirm_Good_RequiredReprompts(t *testing.T) { + SetStdin(strings.NewReader("\ny\n")) + defer SetStdin(nil) + + assert.True(t, Confirm("Proceed?", Required())) +} + func TestQuestion_Good(t *testing.T) { SetStdin(strings.NewReader("alice\n")) defer SetStdin(nil) @@ -110,6 +117,14 @@ func TestQuestion_Bad_EOFReturnsDefault(t *testing.T) { assert.Equal(t, "", Question("Name:", RequiredInput())) } +func TestQuestion_Good_RequiredReprompts(t *testing.T) { + SetStdin(strings.NewReader("\nalice\n")) + defer SetStdin(nil) + + val := Question("Name:", RequiredInput()) + assert.Equal(t, "alice", val) +} + func TestChoose_Good_DefaultIndex(t *testing.T) { SetStdin(strings.NewReader("\n")) defer SetStdin(nil) diff --git a/pkg/cli/utils.go b/pkg/cli/utils.go index 1b47afd..4fcd0c9 100644 --- a/pkg/cli/utils.go +++ b/pkg/cli/utils.go @@ -104,17 +104,21 @@ func Confirm(prompt string, opts ...ConfirmOption) bool { fmt.Printf("%s %s", prompt, suffix) var response string + var readErr error if cfg.timeout > 0 { // Use timeout-based reading resultChan := make(chan string, 1) + errChan := make(chan error, 1) go func() { - line, _ := reader.ReadString('\n') + line, err := reader.ReadString('\n') resultChan <- line + errChan <- err }() select { case response = <-resultChan: + readErr = <-errChan response = strings.ToLower(strings.TrimSpace(response)) case <-time.After(cfg.timeout): fmt.Println() // New line after timeout @@ -122,6 +126,7 @@ func Confirm(prompt string, opts ...ConfirmOption) bool { } } else { line, err := reader.ReadString('\n') + readErr = err if err != nil && line == "" { return cfg.defaultYes } @@ -131,6 +136,10 @@ func Confirm(prompt string, opts ...ConfirmOption) bool { // Handle empty response if response == "" { + if readErr == nil && cfg.required { + fmt.Println("Please enter 'y' or 'n'") + continue + } if cfg.required { return cfg.defaultYes } @@ -241,7 +250,8 @@ func Question(prompt string, opts ...QuestionOption) string { // Handle empty response if response == "" { if cfg.required { - return cfg.defaultValue + fmt.Println("Please enter a value") + continue } response = cfg.defaultValue }