package bonfire import ( "bufio" "fmt" "io" "os" "strconv" "strings" "golang.org/x/term" ) func (c *console) Ask(question, def string) (string, error) { c.writeQuestion(question, def) line, err := c.readLine() if err != nil { if err == io.EOF { return def, nil } return "", err } if line == "" { return def, nil } return line, nil } func (c *console) Confirm(question string, def bool) (bool, error) { if !c.interactive { return def, nil } hint := "y/N" if def { hint = "Y/n" } line, err := c.Ask(question+" ["+hint+"]", "") if err != nil { return false, err } if line == "" { return def, nil } switch strings.ToLower(line) { case "y", "yes": return true, nil case "n", "no": return false, nil default: return def, nil } } func (c *console) Choice(question string, choices []string, def int) (string, error) { if len(choices) == 0 { return "", fmt.Errorf("bonfire: choice has no options") } if def < 0 || def >= len(choices) { def = 0 } c.Println(c.style(ansiCyan, symPrompt) + " " + question) for i, choice := range choices { mark := " " if i == def { mark = "*" } c.Printf(" %s %d) %s\n", mark, i+1, choice) } line, err := c.readLine() if err != nil { if err == io.EOF { return choices[def], nil } return "", err } if line == "" { return choices[def], nil } n, convErr := strconv.Atoi(line) if convErr != nil || n < 1 || n > len(choices) { return choices[def], nil } return choices[n-1], nil } // Secret reads a hidden password on a TTY via term.ReadPassword. // When stdin is not a terminal it reads a plain line and never logs the value. func (c *console) Secret(question string) (string, error) { c.writeQuestion(question, "") if f, ok := c.in.(*os.File); ok && term.IsTerminal(int(f.Fd())) { b, err := term.ReadPassword(int(f.Fd())) c.Println() if err != nil { return "", err } return string(b), nil } line, err := c.readLine() if err != nil { if err == io.EOF { return "", nil } return "", err } return line, nil } func (c *console) writeQuestion(question, def string) { suffix := "" if def != "" { suffix = " " + c.dim("("+def+")") } c.Printf("%s %s%s %s ", c.style(ansiCyan, symPrompt), question, suffix, symArrow) } func (c *console) readLine() (string, error) { if c.in == nil { return "", io.EOF } reader, ok := c.in.(*bufio.Reader) if !ok { reader = bufio.NewReader(c.in) } line, err := reader.ReadString('\n') line = strings.TrimRight(line, "\r\n") if err != nil && err != io.EOF { return "", err } if err == io.EOF && line == "" { return "", io.EOF } return strings.TrimSpace(line), nil }