-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathcliui.go
More file actions
182 lines (160 loc) · 3.66 KB
/
cliui.go
File metadata and controls
182 lines (160 loc) · 3.66 KB
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
package cliui
import (
"flag"
"os"
"sync"
"time"
"github.com/muesli/termenv"
"golang.org/x/xerrors"
"github.com/coder/pretty"
)
var ErrCanceled = xerrors.New("canceled")
// DefaultStyles compose visual elements of the UI.
var DefaultStyles Styles
type Styles struct {
Code,
DateTimeStamp,
Error,
Field,
Hyperlink,
Keyword,
Placeholder,
Prompt,
FocusedPrompt,
Fuchsia,
Warn,
Wrap pretty.Style
}
var (
color termenv.Profile
colorOnce sync.Once
)
var (
// ANSI color codes
red = Color("1")
green = Color("2")
yellow = Color("3")
magenta = Color("5")
white = Color("7")
brightBlue = Color("12")
brightMagenta = Color("13")
)
// Color returns a color for the given string.
func Color(s string) termenv.Color {
colorOnce.Do(func() {
color = termenv.NewOutput(os.Stdout).EnvColorProfile()
if flag.Lookup("test.v") != nil {
// Use a consistent colorless profile in tests so that results
// are deterministic.
color = termenv.Ascii
}
})
return color.Color(s)
}
func isTerm() bool {
return color != termenv.Ascii
}
// Bold returns a formatter that renders text in bold
// if the terminal supports it.
func Bold(s string) string {
if !isTerm() {
return s
}
return pretty.Sprint(pretty.Bold(), s)
}
// BoldFmt returns a formatter that renders text in bold
// if the terminal supports it.
func BoldFmt() pretty.Formatter {
if !isTerm() {
return pretty.Style{}
}
return pretty.Bold()
}
// Timestamp formats a timestamp for display.
func Timestamp(t time.Time) string {
return pretty.Sprint(DefaultStyles.DateTimeStamp, t.Format(time.Stamp))
}
// Keyword formats a keyword for display.
func Keyword(s string) string {
return pretty.Sprint(DefaultStyles.Keyword, s)
}
// Placeholder formats a placeholder for display.
func Placeholder(s string) string {
return pretty.Sprint(DefaultStyles.Placeholder, s)
}
// Wrap prevents the text from overflowing the terminal.
func Wrap(s string) string {
return pretty.Sprint(DefaultStyles.Wrap, s)
}
// Code formats code for display.
func Code(s string) string {
return pretty.Sprint(DefaultStyles.Code, s)
}
// Field formats a field for display.
func Field(s string) string {
return pretty.Sprint(DefaultStyles.Field, s)
}
func ifTerm(fmt pretty.Formatter) pretty.Formatter {
if !isTerm() {
return pretty.Nop
}
return fmt
}
func init() {
// We do not adapt the color based on whether the terminal is light or dark.
// Doing so would require a round-trip between the program and the terminal
// due to the OSC query and response.
DefaultStyles = Styles{
Code: pretty.Style{
ifTerm(pretty.XPad(1, 1)),
pretty.FgColor(Color("#ED567A")),
pretty.BgColor(Color("#2C2C2C")),
},
DateTimeStamp: pretty.Style{
pretty.FgColor(brightBlue),
},
Error: pretty.Style{
pretty.FgColor(red),
},
Field: pretty.Style{
pretty.XPad(1, 1),
pretty.FgColor(Color("#FFFFFF")),
pretty.BgColor(Color("#2B2A2A")),
},
Fuchsia: pretty.Style{
pretty.FgColor(brightMagenta),
},
FocusedPrompt: pretty.Style{
pretty.FgColor(white),
pretty.Wrap("> ", ""),
pretty.FgColor(brightBlue),
},
Hyperlink: pretty.Style{
pretty.FgColor(magenta),
pretty.Underline(),
},
Keyword: pretty.Style{
pretty.FgColor(green),
},
Placeholder: pretty.Style{
pretty.FgColor(magenta),
},
Prompt: pretty.Style{
pretty.FgColor(white),
pretty.Wrap(" ", ""),
},
Warn: pretty.Style{
pretty.FgColor(yellow),
},
Wrap: pretty.Style{
pretty.LineWrap(80),
},
}
}
// ValidateNotEmpty is a helper function to disallow empty inputs!
func ValidateNotEmpty(s string) error {
if s == "" {
return xerrors.New("Must be provided!")
}
return nil
}