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