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 package aurora
37
38
39
40
41
42 type Color uint
43
44
67
68
69 const (
70 BoldFm Color = 1 << iota
71 FaintFm
72 ItalicFm
73 UnderlineFm
74 SlowBlinkFm
75 RapidBlinkFm
76 ReverseFm
77 ConcealFm
78 CrossedOutFm
79
80 FrakturFm
81 DoublyUnderlineFm
82
83 FramedFm
84 EncircledFm
85 OverlinedFm
86
87 InverseFm = ReverseFm
88 BlinkFm = SlowBlinkFm
89 HiddenFm = ConcealFm
90 StrikeThroughFm = CrossedOutFm
91
92 maskFm = BoldFm | FaintFm |
93 ItalicFm | UnderlineFm |
94 SlowBlinkFm | RapidBlinkFm |
95 ReverseFm |
96 ConcealFm | CrossedOutFm |
97
98 FrakturFm | DoublyUnderlineFm |
99
100 FramedFm | EncircledFm | OverlinedFm
101
102 flagFg Color = 1 << 14
103 flagBg Color = 1 << 15
104
105 shiftFg = 16
106 shiftBg = 24
107 )
108
109
110 const (
111
112
113
114
115
116
117
118
119 BlackFg Color = (iota << shiftFg) | flagFg
120 RedFg
121 GreenFg
122 YellowFg
123 BlueFg
124 MagentaFg
125 CyanFg
126 WhiteFg
127
128 BrightFg Color = ((1 << 3) << shiftFg) | flagFg
129
130
131
132
133
134
135
136
137
138 BrownFg = YellowFg
139
140
141 maskFg = (0xff << shiftFg) | flagFg
142 )
143
144
145 const (
146
147
148
149
150
151
152
153
154 BlackBg Color = (iota << shiftBg) | flagBg
155 RedBg
156 GreenBg
157 YellowBg
158 BlueBg
159 MagentaBg
160 CyanBg
161 WhiteBg
162
163 BrightBg Color = ((1 << 3) << shiftBg) | flagBg
164
165
166
167
168
169
170
171
172
173 BrownBg = YellowBg
174
175
176 maskBg = (0xff << shiftBg) | flagBg
177 )
178
179 const (
180 availFlags = "-+# 0"
181 esc = "\033["
182 clear = esc + "0m"
183 )
184
185
186
187
188 func (c Color) IsValid() bool {
189 return true
190 }
191
192
193
194
195
196 func (c Color) Nos(zero bool) string {
197 return string(c.appendNos(make([]byte, 0, 59), zero))
198 }
199
200 func appendCond(bs []byte, cond, semi bool, vals ...byte) []byte {
201 if !cond {
202 return bs
203 }
204 return appendSemi(bs, semi, vals...)
205 }
206
207
208 func appendSemi(bs []byte, semi bool, vals ...byte) []byte {
209 if semi {
210 bs = append(bs, ';')
211 }
212 return append(bs, vals...)
213 }
214
215 func itoa(t byte) string {
216 var (
217 a [3]byte
218 j = 2
219 )
220 for i := 0; i < 3; i, j = i+1, j-1 {
221 a[j] = '0' + t%10
222 if t = t / 10; t == 0 {
223 break
224 }
225 }
226 return string(a[j:])
227 }
228
229 func (c Color) appendFg(bs []byte, zero bool) []byte {
230
231 if zero || c&maskFm != 0 {
232 bs = append(bs, ';')
233 }
234
235
236
237
238
239 switch fg := (c & maskFg) >> shiftFg; {
240 case fg <= 7:
241
242 bs = append(bs, '3', '0'+byte(fg))
243 case fg <= 15:
244
245 bs = append(bs, '9', '0'+byte(fg&^0x08))
246 default:
247 bs = append(bs, '3', '8', ';', '5', ';')
248 bs = append(bs, itoa(byte(fg))...)
249 }
250 return bs
251 }
252
253 func (c Color) appendBg(bs []byte, zero bool) []byte {
254
255 if zero || c&(maskFm|maskFg) != 0 {
256 bs = append(bs, ';')
257 }
258
259
260
261
262
263 switch fg := (c & maskBg) >> shiftBg; {
264 case fg <= 7:
265
266 bs = append(bs, '4', '0'+byte(fg))
267 case fg <= 15:
268
269 bs = append(bs, '1', '0', '0'+byte(fg&^0x08))
270 default:
271 bs = append(bs, '4', '8', ';', '5', ';')
272 bs = append(bs, itoa(byte(fg))...)
273 }
274 return bs
275 }
276
277 func (c Color) appendFm9(bs []byte, zero bool) []byte {
278
279 bs = appendCond(bs, c&ItalicFm != 0,
280 zero || c&(BoldFm|FaintFm) != 0,
281 '3')
282 bs = appendCond(bs, c&UnderlineFm != 0,
283 zero || c&(BoldFm|FaintFm|ItalicFm) != 0,
284 '4')
285
286
287 if c&SlowBlinkFm != 0 {
288 bs = appendSemi(bs,
289 zero || c&(BoldFm|FaintFm|ItalicFm|UnderlineFm) != 0,
290 '5')
291 } else if c&RapidBlinkFm != 0 {
292 bs = appendSemi(bs,
293 zero || c&(BoldFm|FaintFm|ItalicFm|UnderlineFm) != 0,
294 '6')
295 }
296
297
298 const mask6i = BoldFm | FaintFm |
299 ItalicFm | UnderlineFm |
300 SlowBlinkFm | RapidBlinkFm
301
302 bs = appendCond(bs, c&ReverseFm != 0,
303 zero || c&(mask6i) != 0,
304 '7')
305 bs = appendCond(bs, c&ConcealFm != 0,
306 zero || c&(mask6i|ReverseFm) != 0,
307 '8')
308 bs = appendCond(bs, c&CrossedOutFm != 0,
309 zero || c&(mask6i|ReverseFm|ConcealFm) != 0,
310 '9')
311
312 return bs
313 }
314
315
316
317
318
319 func (c Color) appendNos(bs []byte, zero bool) []byte {
320
321 if zero {
322 bs = append(bs, '0')
323 }
324
325
326
327
328 if c&maskFm != 0 {
329
330
331
332
333
334 if c&BoldFm != 0 {
335 bs = appendSemi(bs, zero, '1')
336 } else if c&FaintFm != 0 {
337 bs = appendSemi(bs, zero, '2')
338 }
339
340
341
342 const mask9 = ItalicFm | UnderlineFm |
343 SlowBlinkFm | RapidBlinkFm |
344 ReverseFm | ConcealFm | CrossedOutFm
345
346 if c&mask9 != 0 {
347 bs = c.appendFm9(bs, zero)
348 }
349
350
351
352 const (
353 mask21 = FrakturFm | DoublyUnderlineFm
354 mask9i = BoldFm | FaintFm | mask9
355 )
356
357 if c&mask21 != 0 {
358 bs = appendCond(bs, c&FrakturFm != 0,
359 zero || c&mask9i != 0,
360 '2', '0')
361 bs = appendCond(bs, c&DoublyUnderlineFm != 0,
362 zero || c&(mask9i|FrakturFm) != 0,
363 '2', '1')
364 }
365
366
367
368 const (
369 mask53 = FramedFm | EncircledFm | OverlinedFm
370 mask21i = mask9i | mask21
371 )
372
373 if c&mask53 != 0 {
374 bs = appendCond(bs, c&FramedFm != 0,
375 zero || c&mask21i != 0,
376 '5', '1')
377 bs = appendCond(bs, c&EncircledFm != 0,
378 zero || c&(mask21i|FramedFm) != 0,
379 '5', '2')
380 bs = appendCond(bs, c&OverlinedFm != 0,
381 zero || c&(mask21i|FramedFm|EncircledFm) != 0,
382 '5', '3')
383 }
384
385 }
386
387
388 if c&maskFg != 0 {
389 bs = c.appendFg(bs, zero)
390 }
391
392
393 if c&maskBg != 0 {
394 bs = c.appendBg(bs, zero)
395 }
396
397 return bs
398 }
399
View as plain text