1package ansi
2
3import (
4 "bytes"
5 "strconv"
6)
7
8// writeStyle emits a canonical output style without making capability
9// decisions. Those belong to styleProjector.
10func writeStyle(out *bytes.Buffer, style outputStyle) {
11 out.WriteString("\x1b[0")
12 if style.bold {
13 out.WriteString(";1")
14 }
15 if style.attrs&AttrDim != 0 {
16 out.WriteString(";2")
17 }
18 if style.italic {
19 out.WriteString(";3")
20 }
21 if style.attrs&AttrUnderline != 0 {
22 switch style.underlineStyle {
23 case UnderlineDouble:
24 out.WriteString(";21")
25 case UnderlineCurly:
26 out.WriteString(";4:3")
27 case UnderlineDotted:
28 out.WriteString(";4:4")
29 case UnderlineDashed:
30 out.WriteString(";4:5")
31 default:
32 out.WriteString(";4")
33 }
34 }
35 if style.attrs&AttrBlink != 0 {
36 out.WriteString(";5")
37 }
38 if style.inverse {
39 out.WriteString(";7")
40 }
41 if style.attrs&AttrStrikethrough != 0 {
42 out.WriteString(";9")
43 }
44 var scratch [16]byte
45 writeOutputColor(out, &scratch, style.foreground, 38, 30, 90)
46 writeOutputColor(out, &scratch, style.background, 48, 40, 100)
47 writeUnderlineColor(out, &scratch, style.underlineColor)
48 out.WriteByte('m')
49}
50
51func writeOutputColor(out *bytes.Buffer, scratch *[16]byte, color outputColor, extended, normal, bright int) {
52 switch color.kind {
53 case outputColorANSI16:
54 code := normal + color.index
55 if color.index >= 8 {
56 code = bright + color.index - 8
57 }
58 writeSGRParam(out, scratch, code)
59 case outputColorANSI256:
60 writeExtendedColor(out, scratch, extended, 5, color.index)
61 case outputColorRGB:
62 writeExtendedRGB(out, scratch, extended, color.rgb)
63 }
64}
65
66func writeUnderlineColor(out *bytes.Buffer, scratch *[16]byte, color outputColor) {
67 switch color.kind {
68 case outputColorANSI256:
69 writeExtendedColor(out, scratch, 58, 5, color.index)
70 case outputColorRGB:
71 writeExtendedRGB(out, scratch, 58, color.rgb)
72 }
73}
74
75func writeSGRParam(out *bytes.Buffer, scratch *[16]byte, value int) {
76 out.WriteByte(';')
77 out.Write(strconv.AppendInt(scratch[:0], int64(value), 10))
78}
79
80func writeExtendedColor(out *bytes.Buffer, scratch *[16]byte, selector, mode, value int) {
81 writeSGRParam(out, scratch, selector)
82 writeSGRParam(out, scratch, mode)
83 writeSGRParam(out, scratch, value)
84}
85
86func writeExtendedRGB(out *bytes.Buffer, scratch *[16]byte, selector int, rgb RGB) {
87 writeSGRParam(out, scratch, selector)
88 writeSGRParam(out, scratch, 2)
89 writeSGRParam(out, scratch, int(rgb.R))
90 writeSGRParam(out, scratch, int(rgb.G))
91 writeSGRParam(out, scratch, int(rgb.B))
92}