-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.go
165 lines (136 loc) · 3.97 KB
/
setup.go
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
package delightful
import (
"fmt"
"io"
"os"
"strings"
"github.com/gookit/color"
changecase "github.com/ku/go-change-case"
)
type Message struct {
appName string
colorMode bool
emojiMode bool
verboseMode bool
target io.Writer
}
// New returns a new Output instance with default configuration
func New(appName string) Message {
// set up initial color mode and disable color output if needed
colorMode := allowColor(appName)
if !colorMode {
color.Disable()
}
// choose target io.Writer
target := tryGetTty()
color.SetOutput(target)
// return an instance
return Message{
appName: appName,
colorMode: colorMode,
emojiMode: allowEmoji(appName),
verboseMode: enableVerboseMode(appName),
target: target,
}
}
// SetColorMode controls if the messages are printed with emojis and colors.
// ColorMode is enabled (true) by default.
// May not have any effect if user has disabled color & emojis via environment variable.
// Or if user's terminal environment does not support colors.
func (m *Message) SetColorMode(colorMode bool) {
if allowColor(m.appName) {
m.colorMode = colorMode
if !m.colorMode {
color.Disable()
}
}
}
// SetEmojiMode controls if emojis are printed with the messages:
// Even when colors are enabled!
func (m *Message) SetEmojiMode(emojiMode bool) {
if allowEmoji(m.appName) {
m.emojiMode = emojiMode
}
}
// SetVerboseMode controls additional debug messages.
// Verbose output is disabled by default unless user has set
// VERBOSE or <APP_NAME>_VERBOSE environment variables.
func (m *Message) SetVerboseMode(verboseMode bool) {
m.verboseMode = verboseMode
}
// SetMessageTarget overrides the default output target (tty/stderr).
// Mainly used for testing.
func (m *Message) SetMessageTarget(target io.Writer) {
m.target = target
color.SetOutput(m.target)
}
// allowColor is responsible for ensuring that user configuration is respected
// by checking if user environment dictates coloured output should not be used.
func allowColor(appName string) bool {
// Check if NO_COLOR set https://no-color.org/
if isEnvVarSetOrTruthy("NO_COLOR") {
return false
}
// Check if app-specific _NO_COLOR set https://medium.com/@jdxcode/12-factor-cli-apps-dd3c227a0e46
if isEnvVarSetOrTruthy(formatPrefixedEnvVar(appName, "NO_COLOR")) {
return false
}
// Check if $TERM=dumb https://unix.stackexchange.com/a/43951
if os.Getenv("TERM") == "dumb" {
return false
}
// Otherwise default to colors being enabled
return true
}
// allowEmoji enables separate control of emoji outout
func allowEmoji(appName string) bool {
// if colors are disabled, then disable emojis too
if !allowColor(appName) {
return false
}
// Check if NO_EMOJI
if isEnvVarSetOrTruthy("NO_EMOJI") {
return false
}
// Check if app-specific _NO_EMOJI set https://medium.com/@jdxcode/12-factor-cli-apps-dd3c227a0e46
if isEnvVarSetOrTruthy(formatPrefixedEnvVar(appName, "NO_EMOJI")) {
return false
}
// Otherwise default to emojis being enabled
return true
}
// enableVerboseMode sets the initial verbosity setting by looking at the user
// environment for specific variables.
func enableVerboseMode(appName string) bool {
// Check if NO_COLOR set https://no-color.org/
if isEnvVarSetOrTruthy("VERBOSE") {
return true
}
// Check if app-specific _NO_COLOR set https://medium.com/@jdxcode/12-factor-cli-apps-dd3c227a0e46
if isEnvVarSetOrTruthy(formatPrefixedEnvVar(appName, "VERBOSE")) {
return true
}
return false
}
func isEnvVarSetOrTruthy(envVar string) bool {
value, set := os.LookupEnv(envVar)
// if it's not set at all
if !set {
return false
}
// if it has truthy value
lowerValue := strings.ToLower(value)
if lowerValue == "true" || lowerValue == "1" {
return true
}
// for unset or "falsy value"
return false
}
func formatPrefixedEnvVar(prefix string, envVar string) string {
return fmt.Sprintf(
"%s_%s",
changecase.Constant(strings.TrimSpace(prefix)),
changecase.Constant(strings.TrimSpace(envVar)),
)
}
// TODO allow disable tty