Bladeren bron

use a simpler prompt implementation when we lack a terminal

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 2 jaren geleden
bovenliggende
commit
f1313f3a09
3 gewijzigde bestanden met toevoegingen van 61 en 34 verwijderingen
  1. 1 1
      pkg/compose/remove.go
  2. 55 32
      pkg/prompt/prompt.go
  3. 5 1
      pkg/utils/stringutils.go

+ 1 - 1
pkg/compose/remove.go

@@ -61,7 +61,7 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
 	if options.Force {
 		fmt.Fprintln(s.stdout(), msg)
 	} else {
-		confirm, err := prompt.User{}.Confirm(msg, false)
+		confirm, err := prompt.NewPrompt(s.stdin(), s.stdout()).Confirm(msg, false)
 		if err != nil {
 			return err
 		}

+ 55 - 32
pkg/prompt/prompt.go

@@ -17,42 +17,58 @@
 package prompt
 
 import (
+	"fmt"
+	"io"
+
 	"github.com/AlecAivazis/survey/v2"
+	"github.com/docker/cli/cli/streams"
+	"github.com/docker/compose/v2/pkg/utils"
 )
 
 //go:generate mockgen -destination=./prompt_mock.go -self_package "github.com/docker/compose/v2/pkg/prompt" -package=prompt . UI
 
 // UI - prompt user input
 type UI interface {
-	Select(message string, options []string) (int, error)
-	Input(message string, defaultValue string) (string, error)
 	Confirm(message string, defaultValue bool) (bool, error)
-	Password(message string) (string, error)
 }
 
-// User - aggregates prompt methods
-type User struct{}
-
-// Select - displays a list
-func (u User) Select(message string, options []string) (int, error) {
-	qs := &survey.Select{
-		Message: message,
-		Options: options,
+func NewPrompt(stdin *streams.In, stdout *streams.Out) UI {
+	if stdin.IsTerminal() {
+		return User{stdin: streamsFileReader{stdin}, stdout: streamsFileWriter{stdout}}
 	}
-	var selected int
-	err := survey.AskOne(qs, &selected, nil)
-	return selected, err
+	return Pipe{stdin: stdin, stdout: stdout}
 }
 
-// Input text with default value
-func (u User) Input(message string, defaultValue string) (string, error) {
-	qs := &survey.Input{
-		Message: message,
-		Default: defaultValue,
-	}
-	var s string
-	err := survey.AskOne(qs, &s, nil)
-	return s, err
+// User - in a terminal
+type User struct {
+	stdout streamsFileWriter
+	stdin  streamsFileReader
+}
+
+// adapt streams.Out to terminal.FileWriter
+type streamsFileWriter struct {
+	stream *streams.Out
+}
+
+func (s streamsFileWriter) Write(p []byte) (n int, err error) {
+	return s.stream.Write(p)
+}
+
+func (s streamsFileWriter) Fd() uintptr {
+	return s.stream.FD()
+}
+
+// adapt streams.In to terminal.FileReader
+type streamsFileReader struct {
+	stream *streams.In
+}
+
+func (s streamsFileReader) Read(p []byte) (n int, err error) {
+	return s.stream.Read(p)
+}
+
+func (s streamsFileReader) Fd() uintptr {
+	return s.stream.FD()
 }
 
 // Confirm asks for yes or no input
@@ -62,17 +78,24 @@ func (u User) Confirm(message string, defaultValue bool) (bool, error) {
 		Default: defaultValue,
 	}
 	var b bool
-	err := survey.AskOne(qs, &b, nil)
+	err := survey.AskOne(qs, &b, func(options *survey.AskOptions) error {
+		options.Stdio.In = u.stdin
+		options.Stdio.Out = u.stdout
+		return nil
+	})
 	return b, err
 }
 
-// Password implements a text input with masked characters.
-func (u User) Password(message string) (string, error) {
-	qs := &survey.Password{
-		Message: message,
-	}
-	var p string
-	err := survey.AskOne(qs, &p, nil)
-	return p, err
+// Pipe - aggregates prompt methods
+type Pipe struct {
+	stdout io.Writer
+	stdin  io.Reader
+}
 
+// Confirm asks for yes or no input
+func (u Pipe) Confirm(message string, defaultValue bool) (bool, error) {
+	fmt.Fprint(u.stdout, message)
+	var answer string
+	fmt.Scanln(&answer)
+	return utils.StringToBool(answer), nil
 }

+ 5 - 1
pkg/utils/stringutils.go

@@ -33,6 +33,10 @@ func StringContains(array []string, needle string) bool {
 
 // StringToBool converts a string to a boolean ignoring errors
 func StringToBool(s string) bool {
-	b, _ := strconv.ParseBool(strings.ToLower(strings.TrimSpace(s)))
+	s = strings.ToLower(strings.TrimSpace(s))
+	if s == "y" {
+		return true
+	}
+	b, _ := strconv.ParseBool(s)
 	return b
 }