1package input
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "strings"
8 "syscall"
9
10 "github.com/MichaelMure/git-bug/util/interrupt"
11 "golang.org/x/crypto/ssh/terminal"
12)
13
14func PromptValue(name string, preValue string) (string, error) {
15 return promptValue(name, preValue, false)
16}
17
18func PromptValueRequired(name string, preValue string) (string, error) {
19 return promptValue(name, preValue, true)
20}
21
22func promptValue(name string, preValue string, required bool) (string, error) {
23 for {
24 if preValue != "" {
25 _, _ = fmt.Fprintf(os.Stderr, "%s [%s]: ", name, preValue)
26 } else {
27 _, _ = fmt.Fprintf(os.Stderr, "%s: ", name)
28 }
29
30 line, err := bufio.NewReader(os.Stdin).ReadString('\n')
31 if err != nil {
32 return "", err
33 }
34
35 line = strings.TrimSpace(line)
36
37 if preValue != "" && line == "" {
38 return preValue, nil
39 }
40
41 if required && line == "" {
42 _, _ = fmt.Fprintf(os.Stderr, "%s is empty\n", name)
43 continue
44 }
45
46 return line, nil
47 }
48}
49
50// PromptPassword performs interactive input collection to get the user password
51// while halting echo on the controlling terminal.
52func PromptPassword() (string, error) {
53 termState, err := terminal.GetState(int(syscall.Stdin))
54 if err != nil {
55 return "", err
56 }
57
58 cancel := interrupt.RegisterCleaner(func() error {
59 return terminal.Restore(int(syscall.Stdin), termState)
60 })
61 defer cancel()
62
63 for {
64 fmt.Print("password: ")
65 bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
66 // new line for coherent formatting, ReadPassword clip the normal new line
67 // entered by the user
68 fmt.Println()
69
70 if err != nil {
71 return "", err
72 }
73
74 if len(bytePassword) > 0 {
75 return string(bytePassword), nil
76 }
77
78 fmt.Println("password is empty")
79 }
80}