/
color.go
183 lines (159 loc) · 4.08 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 utils
import (
"fmt"
"strings"
"github.com/coveo/gotemplate/errors"
"github.com/fatih/color"
)
// Attribute is imported from color attribute
type Attribute color.Attribute
// The following constant are copied from the color package in order to get
// the actual names
const (
Reset Attribute = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
// Foreground attributes
const (
FgBlack Attribute = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Foreground attributes high intensity
const (
FgHiBlack Attribute = iota + 90
FgHiRed
FgHiGreen
FgHiYellow
FgHiBlue
FgHiMagenta
FgHiCyan
FgHiWhite
)
// Background attributes
const (
BgBlack Attribute = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// Background attributes high intensity
const (
BgHiBlack Attribute = iota + 100
BgHiRed
BgHiGreen
BgHiYellow
BgHiBlue
BgHiMagenta
BgHiCyan
BgHiWhite
)
var EOL = fmt.Sprintln()
//go:generate stringer -type=Attribute -output generated_colors.go
// Color returns a color attribute build from supplied attribute names
func Color(attributes ...string) (*color.Color, error) {
if nameValues == nil {
nameValues = make(map[string]color.Attribute, BgHiWhite)
for i := Reset; i < BgHiWhite; i++ {
name := strings.ToLower(Attribute(i).String())
if strings.HasPrefix(name, "attribute(") {
continue
}
nameValues[name] = color.Attribute(i)
if strings.HasPrefix(name, "fg") {
nameValues[name[2:]] = color.Attribute(i)
}
}
}
result := color.New()
var containsColor bool
var err errors.Array
for _, attr := range attributes {
for _, attr := range String(attr).FieldsID().Strings() {
if a, match := nameValues[strings.ToLower(attr)]; match {
result.Add(a)
containsColor = true
} else {
err = append(err, fmt.Errorf("Attribute not found %s", attr))
}
}
}
if !containsColor {
return result, fmt.Errorf("No color specified")
}
if len(err) > 0 {
return result, err
}
return result, nil
}
// SprintColor returns a string formated with attributes that are supplied before
func SprintColor(args ...interface{}) (string, error) {
var i int
colorArgs := make([]string, len(args))
for i = 0; i < len(args); i++ {
if _, err := Color(fmt.Sprint(args[i])); err != nil {
break
}
colorArgs[i] = fmt.Sprint(args[i])
}
c, _ := Color(colorArgs...)
return c.Sprint(FormatMessage(args[i:]...)), nil
}
// FormatMessage analyses the arguments to determine if printf or println should be used.
func FormatMessage(args ...interface{}) string {
switch len(args) {
case 0:
return ""
case 1:
return fmt.Sprint(args[0])
default:
if format, args := fmt.Sprint(args[0]), args[1:]; strings.Contains(format, "%") {
if result := fmt.Sprintf(format, args...); !strings.Contains(result, "%!") {
return result
}
}
return strings.TrimSuffix(fmt.Sprintln(args...), EOL)
}
}
var nameValues map[string]color.Attribute
// ColorPrintln call standard fmt.Println function but using the color out stream.
func ColorPrintln(args ...interface{}) (int, error) {
return fmt.Fprintln(color.Output, args...)
}
// ColorPrintf call standard fmt.Printf function but using the color out stream.
func ColorPrintf(format string, args ...interface{}) (int, error) {
return fmt.Fprintf(color.Output, format, args...)
}
// ColorPrint call standard fmt.Printf function but using the color out stream.
func ColorPrint(args ...interface{}) (int, error) {
return fmt.Fprint(color.Output, args...)
}
// ColorErrorPrintln call standard fmt.Println function but using the color out stream.
func ColorErrorPrintln(args ...interface{}) (int, error) {
return fmt.Fprintln(color.Error, args...)
}
// ColorErrorPrintf call standard fmt.Printf function but using the color out stream.
func ColorErrorPrintf(format string, args ...interface{}) (int, error) {
return fmt.Fprintf(color.Error, format, args...)
}
// ColorErrorPrint call standard fmt.Printf function but using the color out stream.
func ColorErrorPrint(args ...interface{}) (int, error) {
return fmt.Fprint(color.Error, args...)
}