Skip to content

Commit f1313f3

Browse files
committed
use a simpler prompt implementation when we lack a terminal
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent a226d01 commit f1313f3

File tree

3 files changed

+61
-34
lines changed

3 files changed

+61
-34
lines changed

pkg/compose/remove.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
6161
if options.Force {
6262
fmt.Fprintln(s.stdout(), msg)
6363
} else {
64-
confirm, err := prompt.User{}.Confirm(msg, false)
64+
confirm, err := prompt.NewPrompt(s.stdin(), s.stdout()).Confirm(msg, false)
6565
if err != nil {
6666
return err
6767
}

pkg/prompt/prompt.go

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,58 @@
1717
package prompt
1818

1919
import (
20+
"fmt"
21+
"io"
22+
2023
"github.com/AlecAivazis/survey/v2"
24+
"github.com/docker/cli/cli/streams"
25+
"github.com/docker/compose/v2/pkg/utils"
2126
)
2227

2328
//go:generate mockgen -destination=./prompt_mock.go -self_package "github.com/docker/compose/v2/pkg/prompt" -package=prompt . UI
2429

2530
// UI - prompt user input
2631
type UI interface {
27-
Select(message string, options []string) (int, error)
28-
Input(message string, defaultValue string) (string, error)
2932
Confirm(message string, defaultValue bool) (bool, error)
30-
Password(message string) (string, error)
3133
}
3234

33-
// User - aggregates prompt methods
34-
type User struct{}
35-
36-
// Select - displays a list
37-
func (u User) Select(message string, options []string) (int, error) {
38-
qs := &survey.Select{
39-
Message: message,
40-
Options: options,
35+
func NewPrompt(stdin *streams.In, stdout *streams.Out) UI {
36+
if stdin.IsTerminal() {
37+
return User{stdin: streamsFileReader{stdin}, stdout: streamsFileWriter{stdout}}
4138
}
42-
var selected int
43-
err := survey.AskOne(qs, &selected, nil)
44-
return selected, err
39+
return Pipe{stdin: stdin, stdout: stdout}
4540
}
4641

47-
// Input text with default value
48-
func (u User) Input(message string, defaultValue string) (string, error) {
49-
qs := &survey.Input{
50-
Message: message,
51-
Default: defaultValue,
52-
}
53-
var s string
54-
err := survey.AskOne(qs, &s, nil)
55-
return s, err
42+
// User - in a terminal
43+
type User struct {
44+
stdout streamsFileWriter
45+
stdin streamsFileReader
46+
}
47+
48+
// adapt streams.Out to terminal.FileWriter
49+
type streamsFileWriter struct {
50+
stream *streams.Out
51+
}
52+
53+
func (s streamsFileWriter) Write(p []byte) (n int, err error) {
54+
return s.stream.Write(p)
55+
}
56+
57+
func (s streamsFileWriter) Fd() uintptr {
58+
return s.stream.FD()
59+
}
60+
61+
// adapt streams.In to terminal.FileReader
62+
type streamsFileReader struct {
63+
stream *streams.In
64+
}
65+
66+
func (s streamsFileReader) Read(p []byte) (n int, err error) {
67+
return s.stream.Read(p)
68+
}
69+
70+
func (s streamsFileReader) Fd() uintptr {
71+
return s.stream.FD()
5672
}
5773

5874
// Confirm asks for yes or no input
@@ -62,17 +78,24 @@ func (u User) Confirm(message string, defaultValue bool) (bool, error) {
6278
Default: defaultValue,
6379
}
6480
var b bool
65-
err := survey.AskOne(qs, &b, nil)
81+
err := survey.AskOne(qs, &b, func(options *survey.AskOptions) error {
82+
options.Stdio.In = u.stdin
83+
options.Stdio.Out = u.stdout
84+
return nil
85+
})
6686
return b, err
6787
}
6888

69-
// Password implements a text input with masked characters.
70-
func (u User) Password(message string) (string, error) {
71-
qs := &survey.Password{
72-
Message: message,
73-
}
74-
var p string
75-
err := survey.AskOne(qs, &p, nil)
76-
return p, err
89+
// Pipe - aggregates prompt methods
90+
type Pipe struct {
91+
stdout io.Writer
92+
stdin io.Reader
93+
}
7794

95+
// Confirm asks for yes or no input
96+
func (u Pipe) Confirm(message string, defaultValue bool) (bool, error) {
97+
fmt.Fprint(u.stdout, message)
98+
var answer string
99+
fmt.Scanln(&answer)
100+
return utils.StringToBool(answer), nil
78101
}

pkg/utils/stringutils.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ func StringContains(array []string, needle string) bool {
3333

3434
// StringToBool converts a string to a boolean ignoring errors
3535
func StringToBool(s string) bool {
36-
b, _ := strconv.ParseBool(strings.ToLower(strings.TrimSpace(s)))
36+
s = strings.ToLower(strings.TrimSpace(s))
37+
if s == "y" {
38+
return true
39+
}
40+
b, _ := strconv.ParseBool(s)
3741
return b
3842
}

0 commit comments

Comments
 (0)