github.com/arunkumar7540/cli@v6.45.0+incompatible/util/ui/prompt.go (about) 1 package ui 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "strconv" 8 9 "github.com/vito/go-interact/interact" 10 "github.com/vito/go-interact/interact/terminal" 11 ) 12 13 const sigIntExitCode = 130 14 15 var ErrInvalidIndex = errors.New("invalid list index") 16 17 type InvalidChoiceError struct { 18 Choice string 19 } 20 21 func (InvalidChoiceError) Error() string { 22 return "Some error" 23 } 24 25 //go:generate counterfeiter . Resolver 26 27 type Resolver interface { 28 Resolve(dst interface{}) error 29 SetIn(io.Reader) 30 SetOut(io.Writer) 31 } 32 33 // DisplayBoolPrompt outputs the prompt and waits for user input. It only 34 // allows for a boolean response. A default boolean response can be set with 35 // defaultResponse. 36 func (ui *UI) DisplayBoolPrompt(defaultResponse bool, template string, templateValues ...map[string]interface{}) (bool, error) { 37 ui.terminalLock.Lock() 38 defer ui.terminalLock.Unlock() 39 40 response := defaultResponse 41 interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...)) 42 interactivePrompt.SetIn(ui.In) 43 interactivePrompt.SetOut(ui.OutForInteration) 44 err := interactivePrompt.Resolve(&response) 45 if isInterrupt(err) { 46 ui.Exiter.Exit(sigIntExitCode) 47 } 48 return response, err 49 } 50 51 // DisplayOptionalTextPrompt outputs the prompt and waits for user input. 52 func (ui *UI) DisplayOptionalTextPrompt(defaultValue string, template string, templateValues ...map[string]interface{}) (string, error) { 53 interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...)) 54 var value = defaultValue 55 interactivePrompt.SetIn(ui.In) 56 interactivePrompt.SetOut(ui.OutForInteration) 57 err := interactivePrompt.Resolve(&value) 58 if isInterrupt(err) { 59 ui.Exiter.Exit(sigIntExitCode) 60 } 61 return value, err 62 } 63 64 // DisplayPasswordPrompt outputs the prompt and waits for user input. Hides 65 // user's response from the screen. 66 func (ui *UI) DisplayPasswordPrompt(template string, templateValues ...map[string]interface{}) (string, error) { 67 ui.terminalLock.Lock() 68 defer ui.terminalLock.Unlock() 69 70 var password interact.Password 71 interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...)) 72 interactivePrompt.SetIn(ui.In) 73 interactivePrompt.SetOut(ui.OutForInteration) 74 err := interactivePrompt.Resolve(interact.Required(&password)) 75 if isInterrupt(err) { 76 ui.Exiter.Exit(sigIntExitCode) 77 } 78 return string(password), err 79 } 80 81 // DisplayTextMenu lets the user choose from a list of options, either by name 82 // or by number. 83 func (ui *UI) DisplayTextMenu(choices []string, promptTemplate string, templateValues ...map[string]interface{}) (string, error) { 84 for i, c := range choices { 85 t := fmt.Sprintf("%d. %s", i+1, c) 86 ui.DisplayText(t) 87 } 88 89 translatedPrompt := ui.TranslateText(promptTemplate, templateValues...) 90 91 interactivePrompt := ui.Interactor.NewInteraction(translatedPrompt) 92 93 interactivePrompt.SetIn(ui.In) 94 interactivePrompt.SetOut(ui.OutForInteration) 95 96 var value string = "enter to skip" 97 err := interactivePrompt.Resolve(&value) 98 99 if isInterrupt(err) { 100 ui.Exiter.Exit(sigIntExitCode) 101 } 102 103 if err != nil { 104 return "", err 105 } 106 107 if value == "enter to skip" { 108 return "", nil 109 } 110 111 i, err := strconv.Atoi(value) 112 if err != nil { 113 if contains(choices, value) { 114 return value, nil 115 } 116 return "", InvalidChoiceError{Choice: value} 117 } 118 119 if i > len(choices) || i <= 0 { 120 return "", ErrInvalidIndex 121 } 122 return choices[i-1], nil 123 } 124 125 // DisplayTextPrompt outputs the prompt and waits for user input. 126 func (ui *UI) DisplayTextPrompt(template string, templateValues ...map[string]interface{}) (string, error) { 127 interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...)) 128 var value string 129 interactivePrompt.SetIn(ui.In) 130 interactivePrompt.SetOut(ui.OutForInteration) 131 err := interactivePrompt.Resolve(interact.Required(&value)) 132 if isInterrupt(err) { 133 ui.Exiter.Exit(sigIntExitCode) 134 } 135 return value, err 136 } 137 138 func contains(s []string, v string) bool { 139 for _, x := range s { 140 if x == v { 141 return true 142 } 143 } 144 return false 145 } 146 147 func isInterrupt(err error) bool { 148 return err == interact.ErrKeyboardInterrupt || err == terminal.ErrKeyboardInterrupt 149 }