aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/mitchellh/cli/ui.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitchellh/cli/ui.go')
-rw-r--r--vendor/github.com/mitchellh/cli/ui.go187
1 files changed, 187 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/cli/ui.go b/vendor/github.com/mitchellh/cli/ui.go
new file mode 100644
index 0000000..a2d6f94
--- /dev/null
+++ b/vendor/github.com/mitchellh/cli/ui.go
@@ -0,0 +1,187 @@
1package cli
2
3import (
4 "bufio"
5 "errors"
6 "fmt"
7 "io"
8 "os"
9 "os/signal"
10 "strings"
11
12 "github.com/bgentry/speakeasy"
13 "github.com/mattn/go-isatty"
14)
15
16// Ui is an interface for interacting with the terminal, or "interface"
17// of a CLI. This abstraction doesn't have to be used, but helps provide
18// a simple, layerable way to manage user interactions.
19type Ui interface {
20 // Ask asks the user for input using the given query. The response is
21 // returned as the given string, or an error.
22 Ask(string) (string, error)
23
24 // AskSecret asks the user for input using the given query, but does not echo
25 // the keystrokes to the terminal.
26 AskSecret(string) (string, error)
27
28 // Output is called for normal standard output.
29 Output(string)
30
31 // Info is called for information related to the previous output.
32 // In general this may be the exact same as Output, but this gives
33 // Ui implementors some flexibility with output formats.
34 Info(string)
35
36 // Error is used for any error messages that might appear on standard
37 // error.
38 Error(string)
39
40 // Warn is used for any warning messages that might appear on standard
41 // error.
42 Warn(string)
43}
44
45// BasicUi is an implementation of Ui that just outputs to the given
46// writer. This UI is not threadsafe by default, but you can wrap it
47// in a ConcurrentUi to make it safe.
48type BasicUi struct {
49 Reader io.Reader
50 Writer io.Writer
51 ErrorWriter io.Writer
52}
53
54func (u *BasicUi) Ask(query string) (string, error) {
55 return u.ask(query, false)
56}
57
58func (u *BasicUi) AskSecret(query string) (string, error) {
59 return u.ask(query, true)
60}
61
62func (u *BasicUi) ask(query string, secret bool) (string, error) {
63 if _, err := fmt.Fprint(u.Writer, query+" "); err != nil {
64 return "", err
65 }
66
67 // Register for interrupts so that we can catch it and immediately
68 // return...
69 sigCh := make(chan os.Signal, 1)
70 signal.Notify(sigCh, os.Interrupt)
71 defer signal.Stop(sigCh)
72
73 // Ask for input in a go-routine so that we can ignore it.
74 errCh := make(chan error, 1)
75 lineCh := make(chan string, 1)
76 go func() {
77 var line string
78 var err error
79 if secret && isatty.IsTerminal(os.Stdin.Fd()) {
80 line, err = speakeasy.Ask("")
81 } else {
82 r := bufio.NewReader(u.Reader)
83 line, err = r.ReadString('\n')
84 }
85 if err != nil {
86 errCh <- err
87 return
88 }
89
90 lineCh <- strings.TrimRight(line, "\r\n")
91 }()
92
93 select {
94 case err := <-errCh:
95 return "", err
96 case line := <-lineCh:
97 return line, nil
98 case <-sigCh:
99 // Print a newline so that any further output starts properly
100 // on a new line.
101 fmt.Fprintln(u.Writer)
102
103 return "", errors.New("interrupted")
104 }
105}
106
107func (u *BasicUi) Error(message string) {
108 w := u.Writer
109 if u.ErrorWriter != nil {
110 w = u.ErrorWriter
111 }
112
113 fmt.Fprint(w, message)
114 fmt.Fprint(w, "\n")
115}
116
117func (u *BasicUi) Info(message string) {
118 u.Output(message)
119}
120
121func (u *BasicUi) Output(message string) {
122 fmt.Fprint(u.Writer, message)
123 fmt.Fprint(u.Writer, "\n")
124}
125
126func (u *BasicUi) Warn(message string) {
127 u.Error(message)
128}
129
130// PrefixedUi is an implementation of Ui that prefixes messages.
131type PrefixedUi struct {
132 AskPrefix string
133 AskSecretPrefix string
134 OutputPrefix string
135 InfoPrefix string
136 ErrorPrefix string
137 WarnPrefix string
138 Ui Ui
139}
140
141func (u *PrefixedUi) Ask(query string) (string, error) {
142 if query != "" {
143 query = fmt.Sprintf("%s%s", u.AskPrefix, query)
144 }
145
146 return u.Ui.Ask(query)
147}
148
149func (u *PrefixedUi) AskSecret(query string) (string, error) {
150 if query != "" {
151 query = fmt.Sprintf("%s%s", u.AskSecretPrefix, query)
152 }
153
154 return u.Ui.AskSecret(query)
155}
156
157func (u *PrefixedUi) Error(message string) {
158 if message != "" {
159 message = fmt.Sprintf("%s%s", u.ErrorPrefix, message)
160 }
161
162 u.Ui.Error(message)
163}
164
165func (u *PrefixedUi) Info(message string) {
166 if message != "" {
167 message = fmt.Sprintf("%s%s", u.InfoPrefix, message)
168 }
169
170 u.Ui.Info(message)
171}
172
173func (u *PrefixedUi) Output(message string) {
174 if message != "" {
175 message = fmt.Sprintf("%s%s", u.OutputPrefix, message)
176 }
177
178 u.Ui.Output(message)
179}
180
181func (u *PrefixedUi) Warn(message string) {
182 if message != "" {
183 message = fmt.Sprintf("%s%s", u.WarnPrefix, message)
184 }
185
186 u.Ui.Warn(message)
187}