-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
color.go
164 lines (148 loc) · 2.96 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
// Package color can be used to add color to your terminal using ANSI escape code (or sequences).
//
// See https://en.wikipedia.org/wiki/ANSI_escape_code
// Copy modified from https://github.com/fatih/color
// Copyright 2013 Fatih Arslan
package color
import (
"fmt"
"strconv"
"strings"
)
// Attribute defines a single SGR (Select Graphic Rendition) code.
type Attribute int
// Base attributes
const (
Reset Attribute = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
// Foreground text colors
const (
FgBlack Attribute = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Foreground Hi-Intensity text colors
const (
FgHiBlack Attribute = iota + 90
FgHiRed
FgHiGreen
FgHiYellow
FgHiBlue
FgHiMagenta
FgHiCyan
FgHiWhite
)
// Background text colors
const (
BgBlack Attribute = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// Background Hi-Intensity text colors
const (
BgHiBlack Attribute = iota + 100
BgHiRed
BgHiGreen
BgHiYellow
BgHiBlue
BgHiMagenta
BgHiCyan
BgHiWhite
)
const (
escape = "\x1b"
unescape = "\\x1b"
)
// Format text for terminal.
// You can pass an arbitrary number of Attribute or []Attribute followed by any other values,
// that can either be a string or something else (that is converted to string using fmt.Sprint).
func Format(s ...interface{}) string {
if len(s) == 0 {
return ""
}
params := []Attribute{}
in := -1
for i, v := range s {
switch vt := v.(type) {
case []Attribute:
if in == -1 {
params = append(params, vt...)
} else {
s[i] = printExtraColorAttribute(v)
}
case Attribute:
if in == -1 {
params = append(params, vt)
} else {
s[i] = printExtraColorAttribute(v)
}
default:
if in == -1 {
in = i
}
}
}
if in == -1 || len(s[in:]) == 0 {
return ""
}
return wrap(params, fmt.Sprint(s[in:]...))
}
func printExtraColorAttribute(v interface{}) string {
return fmt.Sprintf("(EXTRA color.Attribute=%v)", v)
}
// StripAttributes from input arguments and return unformatted text.
func StripAttributes(s ...interface{}) (raw string) {
in := -1
for i, v := range s {
switch v.(type) {
case []Attribute, Attribute:
if in != -1 {
s[i] = printExtraColorAttribute(v)
}
default:
if in == -1 {
in = i
}
}
}
if in == -1 {
in = 0
}
return fmt.Sprint(s[in:]...)
}
// Escape text for terminal.
func Escape(s string) string {
return strings.Replace(s, escape, unescape, -1)
}
// sequence returns a formated SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan.
func sequence(params []Attribute) string {
format := make([]string, len(params))
for i, v := range params {
format[i] = strconv.Itoa(int(v))
}
return strings.Join(format, ";")
}
// wrap the s string with the colors attributes.
func wrap(params []Attribute, s string) string {
return fmt.Sprintf("%s[%sm%s%s[%dm", escape, sequence(params), s, escape, Reset)
}