Skip to content

Commit bcc739d

Browse files
authored
Merge pull request #3606 from ActiveState/mitchell/dx-3166-3
Show prompts, even if running in non-interactive or force mode.
2 parents c10ecc4 + 878565b commit bcc739d

File tree

2 files changed

+154
-63
lines changed

2 files changed

+154
-63
lines changed

internal/prompt/overrides.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,34 @@ import (
66

77
type Select struct {
88
*survey.Select
9+
nonInteractiveChoice *string
10+
}
11+
12+
func (s *Select) Prompt() (interface{}, error) {
13+
if s.nonInteractiveChoice == nil {
14+
return s.Select.Prompt()
15+
}
16+
17+
idx := 0
18+
for i, choice := range s.Select.Options {
19+
if choice == *s.nonInteractiveChoice {
20+
idx = i
21+
break
22+
}
23+
}
24+
25+
err := s.Select.Render(
26+
survey.SelectQuestionTemplate,
27+
survey.SelectTemplateData{
28+
Select: *s.Select,
29+
PageEntries: s.Select.Options,
30+
SelectedIndex: idx,
31+
})
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
return *s.nonInteractiveChoice, nil
937
}
1038

1139
func (s *Select) Cleanup(interface{}) error {
@@ -15,6 +43,22 @@ func (s *Select) Cleanup(interface{}) error {
1543

1644
type Input struct {
1745
*survey.Input
46+
nonInteractiveResponse *string
47+
}
48+
49+
func (i *Input) Prompt() (interface{}, error) {
50+
if i.nonInteractiveResponse == nil {
51+
return i.Input.Prompt()
52+
}
53+
54+
err := i.Input.Render(
55+
survey.InputQuestionTemplate,
56+
survey.InputTemplateData{Input: *i.Input})
57+
if err != nil {
58+
return nil, err
59+
}
60+
61+
return *i.nonInteractiveResponse, nil
1862
}
1963

2064
func (i *Input) Cleanup(val interface{}) error {
@@ -33,6 +77,22 @@ func (i *Password) Cleanup(val interface{}) error {
3377

3478
type Confirm struct {
3579
*survey.Confirm
80+
nonInteractiveChoice *bool
81+
}
82+
83+
func (s *Confirm) Prompt() (interface{}, error) {
84+
if s.nonInteractiveChoice == nil {
85+
return s.Confirm.Prompt()
86+
}
87+
88+
err := s.Confirm.Render(
89+
survey.ConfirmQuestionTemplate,
90+
survey.ConfirmTemplateData{Confirm: *s.Confirm})
91+
if err != nil {
92+
return nil, err
93+
}
94+
95+
return *s.nonInteractiveChoice, nil
3696
}
3797

3898
func (s *Confirm) Cleanup(interface{}) error {

internal/prompt/prompt.go

Lines changed: 94 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -106,26 +106,6 @@ func interactiveInputError(message string) error {
106106
// If the prompt is non-interactive, it returns defaultResponse.
107107
// If the prompt is forced, it returns forcedResponse if not nil, or defaultResponse.
108108
func (p *Prompt) InputAndValidate(title, message string, defaultResponse *string, forcedResponse *string, validator ValidatorFunc, flags ...ValidatorFlag) (string, error) {
109-
if p.isForced {
110-
response := forcedResponse
111-
if response == nil {
112-
response = defaultResponse
113-
}
114-
if response != nil {
115-
p.out.Notice(locale.Tr("prompt_using_force", *response))
116-
return *response, nil
117-
}
118-
return "", ErrNoForceOption
119-
}
120-
121-
if !p.isInteractive {
122-
if defaultResponse != nil {
123-
p.out.Notice(locale.Tr("prompt_using_non_interactive", *defaultResponse))
124-
return *defaultResponse, nil
125-
}
126-
return "", interactiveInputError(message)
127-
}
128-
129109
var response string
130110
flagValidators, err := processValidators(flags)
131111
if err != nil {
@@ -139,6 +119,29 @@ func (p *Prompt) InputAndValidate(title, message string, defaultResponse *string
139119
p.out.Notice(output.Emphasize(title))
140120
}
141121

122+
var nonInteractiveResponse *string
123+
124+
if p.isForced {
125+
nonInteractiveResponse = forcedResponse
126+
if nonInteractiveResponse == nil {
127+
nonInteractiveResponse = defaultResponse
128+
}
129+
if nonInteractiveResponse == nil {
130+
return "", ErrNoForceOption
131+
}
132+
}
133+
134+
if !p.isInteractive {
135+
nonInteractiveResponse = defaultResponse
136+
if nonInteractiveResponse == nil {
137+
return "", interactiveInputError(message)
138+
}
139+
}
140+
141+
if p.out.Type().IsStructured() {
142+
return *nonInteractiveResponse, nil
143+
}
144+
142145
// We handle defaults more clearly than the survey package can
143146
if defaultResponse != nil && *defaultResponse != "" {
144147
v, err := p.Select("", formatMessage(message, !p.out.Config().Colored), []string{*defaultResponse, locale.Tl("prompt_custom", "Other ..")}, defaultResponse, forcedResponse)
@@ -153,45 +156,55 @@ func (p *Prompt) InputAndValidate(title, message string, defaultResponse *string
153156

154157
err = survey.AskOne(&Input{&survey.Input{
155158
Message: formatMessage(message, !p.out.Config().Colored),
156-
}}, &response, validator)
159+
}, nonInteractiveResponse}, &response, validator)
157160
if err != nil {
158161
return "", locale.NewInputError(err.Error())
159162
}
160163

164+
switch {
165+
case p.isForced:
166+
p.out.Notice(locale.Tr("prompt_using_force", response))
167+
case !p.isInteractive:
168+
p.out.Notice(locale.Tr("prompt_using_non_interactive", response))
169+
}
170+
161171
return response, nil
162172
}
163173

164174
// Select prompts the user to select one entry from multiple choices.
165175
// If the prompt is non-interactive, it returns defaultChoice.
166176
// If the prompt is forced, it returns forcedChoice if not nil, or defaultChoice.
167177
func (p *Prompt) Select(title, message string, choices []string, defaultChoice *string, forcedChoice *string) (string, error) {
178+
if title != "" {
179+
p.out.Notice(output.Emphasize(title))
180+
}
181+
182+
var defChoice string
183+
if defaultChoice != nil {
184+
defChoice = *defaultChoice
185+
}
186+
187+
var nonInteractiveChoice *string
188+
168189
if p.isForced {
169-
choice := forcedChoice
170-
if choice == nil {
171-
choice = defaultChoice
190+
nonInteractiveChoice = forcedChoice
191+
if nonInteractiveChoice == nil {
192+
nonInteractiveChoice = defaultChoice
172193
}
173-
if choice != nil {
174-
p.out.Notice(locale.Tr("prompt_using_force", *choice))
175-
return *choice, nil
194+
if nonInteractiveChoice == nil {
195+
return "", ErrNoForceOption
176196
}
177-
return "", ErrNoForceOption
178197
}
179198

180199
if !p.isInteractive {
181-
if defaultChoice != nil {
182-
p.out.Notice(locale.Tr("prompt_using_non_interactive", *defaultChoice))
183-
return *defaultChoice, nil
200+
nonInteractiveChoice = defaultChoice
201+
if nonInteractiveChoice == nil {
202+
return "", interactiveInputError(message)
184203
}
185-
return "", interactiveInputError(message)
186204
}
187205

188-
if title != "" {
189-
p.out.Notice(output.Emphasize(title))
190-
}
191-
192-
var defChoice string
193-
if defaultChoice != nil {
194-
defChoice = *defaultChoice
206+
if p.out.Type().IsStructured() {
207+
return *nonInteractiveChoice, nil
195208
}
196209

197210
var response string
@@ -200,55 +213,64 @@ func (p *Prompt) Select(title, message string, choices []string, defaultChoice *
200213
Options: choices,
201214
Default: defChoice,
202215
FilterFn: func(input string, choices []string) []string { return choices }, // no filter
203-
}}, &response, nil)
216+
}, nonInteractiveChoice}, &response, nil)
204217
if err != nil {
205218
return "", locale.NewInputError(err.Error())
206219
}
220+
221+
switch {
222+
case p.isForced:
223+
p.out.Notice(locale.Tr("prompt_using_force", response))
224+
case !p.isInteractive:
225+
p.out.Notice(locale.Tr("prompt_using_non_interactive", response))
226+
}
227+
207228
return response, nil
208229
}
209230

210231
// Confirm prompts user for yes or no response.
211232
// If the prompt is non-interactive, it returns defaultChoice.
212233
// If the prompt is forced, it returns forcedChoice if not nil, or defaultChoice.
213234
func (p *Prompt) Confirm(title, message string, defaultChoice *bool, forcedChoice *bool) (bool, error) {
235+
p.analytics.EventWithLabel(constants.CatPrompt, title, "present")
236+
237+
if title != "" {
238+
p.out.Notice(output.Emphasize(title))
239+
}
240+
241+
var defChoice bool
242+
if defaultChoice != nil {
243+
defChoice = *defaultChoice
244+
}
245+
246+
var nonInteractiveChoice *bool
247+
214248
if p.isForced {
215-
choice := forcedChoice
216-
if choice == nil {
217-
choice = defaultChoice
249+
nonInteractiveChoice = forcedChoice
250+
if nonInteractiveChoice == nil {
251+
nonInteractiveChoice = defaultChoice
218252
}
219-
if choice != nil {
220-
p.out.Notice(locale.T("prompt_continue_force"))
221-
return *choice, nil
253+
if nonInteractiveChoice == nil {
254+
return false, ErrNoForceOption
222255
}
223-
return false, ErrNoForceOption
224256
}
225257

226258
if !p.isInteractive {
227-
if defaultChoice != nil {
228-
if *defaultChoice {
229-
p.out.Notice(locale.T("prompt_continue_non_interactive"))
230-
return true, nil
231-
}
232-
return false, locale.NewInputError("prompt_abort_non_interactive")
259+
nonInteractiveChoice = defaultChoice
260+
if nonInteractiveChoice == nil {
261+
return false, interactiveInputError(message)
233262
}
234-
return false, interactiveInputError(message)
235263
}
236-
if title != "" {
237-
p.out.Notice(output.Emphasize(title))
238-
}
239-
240-
p.analytics.EventWithLabel(constants.CatPrompt, title, "present")
241264

242-
var defChoice bool
243-
if defaultChoice != nil {
244-
defChoice = *defaultChoice
265+
if p.out.Type().IsStructured() {
266+
return *nonInteractiveChoice, nil
245267
}
246268

247269
var resp bool
248270
err := survey.AskOne(&Confirm{&survey.Confirm{
249271
Message: formatMessage(strings.TrimSuffix(message, "\n"), !p.out.Config().Colored),
250272
Default: defChoice,
251-
}}, &resp, nil)
273+
}, nonInteractiveChoice}, &resp, nil)
252274
if err != nil {
253275
if err == terminal.InterruptErr {
254276
p.analytics.EventWithLabel(constants.CatPrompt, title, "interrupt")
@@ -257,6 +279,15 @@ func (p *Prompt) Confirm(title, message string, defaultChoice *bool, forcedChoic
257279
}
258280
p.analytics.EventWithLabel(constants.CatPrompt, title, translateConfirm(resp))
259281

282+
switch {
283+
case p.isForced:
284+
p.out.Notice(locale.T("prompt_continue_force"))
285+
case !p.isInteractive && resp:
286+
p.out.Notice(locale.T("prompt_continue_non_interactive"))
287+
case !p.isInteractive && !resp:
288+
return false, locale.NewInputError("prompt_abort_non_interactive")
289+
}
290+
260291
return resp, nil
261292
}
262293

0 commit comments

Comments
 (0)