github.com/supabase/cli@v1.168.1/internal/utils/console.go (about) 1 package utils 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 "strings" 9 10 "golang.org/x/term" 11 ) 12 13 type Console struct { 14 IsTTY bool 15 stdin *bufio.Scanner 16 logger io.Writer 17 } 18 19 func NewConsole() Console { 20 return Console{ 21 IsTTY: term.IsTerminal(int(os.Stdin.Fd())), 22 stdin: bufio.NewScanner(os.Stdin), 23 logger: GetDebugLogger(), 24 } 25 } 26 27 // PromptYesNo asks yes/no questions using the label. 28 func (c Console) PromptYesNo(label string, def bool) bool { 29 choices := "Y/n" 30 if !def { 31 choices = "y/N" 32 } 33 labelWithChoice := fmt.Sprintf("%s [%s] ", label, choices) 34 // Any error will be handled as default value 35 if input := c.PromptText(labelWithChoice); len(input) > 0 { 36 if answer := parseYesNo(input); answer != nil { 37 return *answer 38 } 39 } 40 return def 41 } 42 43 func parseYesNo(s string) *bool { 44 s = strings.ToLower(s) 45 if s == "y" || s == "yes" { 46 return Ptr(true) 47 } 48 if s == "n" || s == "no" { 49 return Ptr(false) 50 } 51 return nil 52 } 53 54 // PromptText asks for input using the label. 55 func (c Console) PromptText(label string) string { 56 fmt.Fprint(os.Stderr, label) 57 // Scan a single line from input or file 58 if !c.stdin.Scan() { 59 fmt.Fprintln(c.logger, io.EOF) 60 } 61 if err := c.stdin.Err(); err != nil { 62 fmt.Fprintln(c.logger, err) 63 } 64 token := strings.TrimSpace(c.stdin.Text()) 65 // Echo input to stderr for non-interactive terminals 66 if !c.IsTTY { 67 fmt.Fprintln(os.Stderr, token) 68 } 69 return token 70 }