-
Notifications
You must be signed in to change notification settings - Fork 119
/
color.go
183 lines (159 loc) · 3.78 KB
/
color.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package text
import (
"fmt"
"sort"
"strconv"
"strings"
"sync"
)
var (
colorsEnabled = areANSICodesSupported()
)
// DisableColors (forcefully) disables color coding globally.
func DisableColors() {
colorsEnabled = false
}
// EnableColors (forcefully) enables color coding globally.
func EnableColors() {
colorsEnabled = true
}
// The logic here is inspired from github.com/fatih/color; the following is
// the the bare minimum logic required to print Colored to the console.
// The differences:
// * This one caches the escape sequences for cases with multiple colors
// * This one handles cases where the incoming already has colors in the
// form of escape sequences; in which case, text that does not have any
// escape sequences are colored/escaped
// Color represents a single color to render with.
type Color int
// Base colors -- attributes in reality
const (
Reset Color = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
// Foreground colors
const (
FgBlack Color = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Foreground Hi-Intensity colors
const (
FgHiBlack Color = iota + 90
FgHiRed
FgHiGreen
FgHiYellow
FgHiBlue
FgHiMagenta
FgHiCyan
FgHiWhite
)
// Background colors
const (
BgBlack Color = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// Background Hi-Intensity colors
const (
BgHiBlack Color = iota + 100
BgHiRed
BgHiGreen
BgHiYellow
BgHiBlue
BgHiMagenta
BgHiCyan
BgHiWhite
)
// EscapeSeq returns the ANSI escape sequence for the color.
func (c Color) EscapeSeq() string {
return EscapeStart + strconv.Itoa(int(c)) + EscapeStop
}
// HTMLProperty returns the "class" attribute for the color.
func (c Color) HTMLProperty() string {
out := ""
if class, ok := colorCSSClassMap[c]; ok {
out = fmt.Sprintf("class=\"%s\"", class)
}
return out
}
// Sprint colorizes and prints the given string(s).
func (c Color) Sprint(a ...interface{}) string {
return colorize(fmt.Sprint(a...), c.EscapeSeq())
}
// Sprintf formats and colorizes and prints the given string(s).
func (c Color) Sprintf(format string, a ...interface{}) string {
return colorize(fmt.Sprintf(format, a...), c.EscapeSeq())
}
// Colors represents an array of Color objects to render with.
// Example: Colors{FgCyan, BgBlack}
type Colors []Color
var (
// colorsSeqMap caches the escape sequence for a set of colors
colorsSeqMap = sync.Map{}
)
// EscapeSeq returns the ANSI escape sequence for the colors set.
func (c Colors) EscapeSeq() string {
if len(c) == 0 {
return ""
}
colorsKey := fmt.Sprintf("%#v", c)
escapeSeq, ok := colorsSeqMap.Load(colorsKey)
if !ok || escapeSeq == "" {
colorNums := make([]string, len(c))
for idx, color := range c {
colorNums[idx] = strconv.Itoa(int(color))
}
escapeSeq = EscapeStart + strings.Join(colorNums, ";") + EscapeStop
colorsSeqMap.Store(colorsKey, escapeSeq)
}
return escapeSeq.(string)
}
// HTMLProperty returns the "class" attribute for the colors.
func (c Colors) HTMLProperty() string {
if len(c) == 0 {
return ""
}
var classes []string
for _, color := range c {
if class, ok := colorCSSClassMap[color]; ok {
classes = append(classes, class)
}
}
if len(classes) > 1 {
sort.Strings(classes)
}
return fmt.Sprintf("class=\"%s\"", strings.Join(classes, " "))
}
// Sprint colorizes and prints the given string(s).
func (c Colors) Sprint(a ...interface{}) string {
return colorize(fmt.Sprint(a...), c.EscapeSeq())
}
// Sprintf formats and colorizes and prints the given string(s).
func (c Colors) Sprintf(format string, a ...interface{}) string {
return colorize(fmt.Sprintf(format, a...), c.EscapeSeq())
}
func colorize(s string, escapeSeq string) string {
if !colorsEnabled || escapeSeq == "" {
return s
}
return Escape(s, escapeSeq)
}