Skip to content

Commit

Permalink
add: interactive confirm printer option to wait for confirmation answer
Browse files Browse the repository at this point in the history
  • Loading branch information
KarolosLykos authored and KarolosLykos committed Mar 8, 2024
1 parent 1800c6e commit ab17a1b
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 7 deletions.
40 changes: 33 additions & 7 deletions interactive_confirm_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type InteractiveConfirmPrinter struct {
RejectStyle *Style
SuffixStyle *Style
OnInterruptFunc func()
Confirmation bool
}

// WithDefaultText sets the default text.
Expand All @@ -58,13 +59,13 @@ func (p InteractiveConfirmPrinter) WithTextStyle(style *Style) *InteractiveConfi
return &p
}

// WithConfirmText sets the confirm text.
// WithConfirmText sets the confirmation text.
func (p InteractiveConfirmPrinter) WithConfirmText(text string) *InteractiveConfirmPrinter {
p.ConfirmText = text
return &p
}

// WithConfirmStyle sets the confirm style.
// WithConfirmStyle sets the confirmation style.
func (p InteractiveConfirmPrinter) WithConfirmStyle(style *Style) *InteractiveConfirmPrinter {
p.ConfirmStyle = style
return &p
Expand All @@ -88,7 +89,7 @@ func (p InteractiveConfirmPrinter) WithSuffixStyle(style *Style) *InteractiveCon
return &p
}

// OnInterrupt sets the function to execute on exit of the input reader
// WithOnInterruptFunc sets the function to execute on exit of the input reader
func (p InteractiveConfirmPrinter) WithOnInterruptFunc(exitFunc func()) *InteractiveConfirmPrinter {
p.OnInterruptFunc = exitFunc
return &p
Expand All @@ -100,7 +101,12 @@ func (p InteractiveConfirmPrinter) WithDelimiter(delimiter string) *InteractiveC
return &p
}

// Show shows the confirm prompt.
func (p InteractiveConfirmPrinter) WithConfirmation(value bool) *InteractiveConfirmPrinter {
p.Confirmation = value
return &p
}

// Show shows the confirmation prompt.
//
// Example:
//
Expand All @@ -113,6 +119,7 @@ func (p InteractiveConfirmPrinter) Show(text ...string) (bool, error) {
defer exit()

var result bool
var resultFlag bool

if len(text) == 0 || text[0] == "" {
text = []string{p.DefaultText}
Expand All @@ -134,16 +141,29 @@ func (p InteractiveConfirmPrinter) Show(text ...string) (bool, error) {
switch char {
case y:
p.ConfirmStyle.Print(p.ConfirmText)
Println()
result = true
Println()
if p.Confirmation {
p.renderHelp()
resultFlag = true
return false, nil
}
return true, nil
case n:
p.RejectStyle.Print(p.RejectText)
Println()
result = false
Println()
if p.Confirmation {
p.renderHelp()
resultFlag = true
return false, nil
}
return true, nil
}
case keys.Enter:
if p.Confirmation && resultFlag {
return true, nil
}
if p.DefaultValue {
p.ConfirmStyle.Print(p.ConfirmText)
} else {
Expand All @@ -165,7 +185,7 @@ func (p InteractiveConfirmPrinter) Show(text ...string) (bool, error) {
return result, err
}

// getShortHandles returns the short hand answers for the confirmation prompt
// getShortHandles returns the shorthand answers for the confirmation prompt
func (p InteractiveConfirmPrinter) getShortHandles() (string, string) {
y := strings.ToLower(string([]rune(p.ConfirmText)[0]))
n := strings.ToLower(string([]rune(p.RejectText)[0]))
Expand All @@ -184,3 +204,9 @@ func (p InteractiveConfirmPrinter) getSuffix() string {

return p.SuffixStyle.Sprintf("[%s/%s]", y, n)
}

func (p *InteractiveConfirmPrinter) renderHelp() {
help := fmt.Sprintf("(Press enter to confirm)")

Check failure on line 209 in interactive_confirm_printer.go

View workflow job for this annotation

GitHub Actions / lint

S1039: unnecessary use of fmt.Sprintf (gosimple)

ThemeDefault.SecondaryStyle.Println(help)
}
42 changes: 42 additions & 0 deletions interactive_confirm_printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pterm_test
import (
"reflect"
"testing"
"time"

"atomicgo.dev/keyboard"
"atomicgo.dev/keyboard/keys"
Expand Down Expand Up @@ -82,6 +83,47 @@ func TestInteractiveConfirmPrinter_WithRejectText(t *testing.T) {
testza.AssertEqual(t, p.RejectText, "reject")
}

func TestInteractiveConfirmPrinter_WithConfirmation(t *testing.T) {
p := pterm.DefaultInteractiveConfirm.WithConfirmation(true)
testza.AssertEqual(t, p.Confirmation, true)
}

func TestInteractiveConfirmPrinter_WithConfirmation_true(t *testing.T) {
p := pterm.DefaultInteractiveConfirm.WithConfirmation(true)
tests := []struct {
name string
key string
expected bool
}{
{
name: "Confirm",
key: "y",
expected: true,
},
{
name: "Reject",
key: "n",
expected: false,
},
{
name: "Default_Value",
key: keys.Enter.String(),
expected: p.DefaultValue,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
go func() {
keyboard.SimulateKeyPress(tc.key)
time.Sleep(100 * time.Millisecond)
keyboard.SimulateKeyPress(keys.Enter)
}()
result, _ := p.Show()
testza.AssertEqual(t, result, tc.expected)
})
}
}

func TestInteractiveConfirmPrinter_CustomAnswers(t *testing.T) {
p := pterm.DefaultInteractiveConfirm.WithRejectText("reject").WithConfirmText("accept")
tests := []struct {
Expand Down

0 comments on commit ab17a1b

Please sign in to comment.