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
|
package cellbuf
import (
"bytes"
"image/color"
"github.com/charmbracelet/x/ansi"
)
// ReadStyle reads a Select Graphic Rendition (SGR) escape sequences from a
// list of parameters.
func ReadStyle(params ansi.Params, pen *Style) {
if len(params) == 0 {
pen.Reset()
return
}
for i := 0; i < len(params); i++ {
param, hasMore, _ := params.Param(i, 0)
switch param {
case 0: // Reset
pen.Reset()
case 1: // Bold
pen.Bold(true)
case 2: // Dim/Faint
pen.Faint(true)
case 3: // Italic
pen.Italic(true)
case 4: // Underline
nextParam, _, ok := params.Param(i+1, 0)
if hasMore && ok { // Only accept subparameters i.e. separated by ":"
switch nextParam {
case 0, 1, 2, 3, 4, 5:
i++
switch nextParam {
case 0: // No Underline
pen.UnderlineStyle(NoUnderline)
case 1: // Single Underline
pen.UnderlineStyle(SingleUnderline)
case 2: // Double Underline
pen.UnderlineStyle(DoubleUnderline)
case 3: // Curly Underline
pen.UnderlineStyle(CurlyUnderline)
case 4: // Dotted Underline
pen.UnderlineStyle(DottedUnderline)
case 5: // Dashed Underline
pen.UnderlineStyle(DashedUnderline)
}
}
} else {
// Single Underline
pen.Underline(true)
}
case 5: // Slow Blink
pen.SlowBlink(true)
case 6: // Rapid Blink
pen.RapidBlink(true)
case 7: // Reverse
pen.Reverse(true)
case 8: // Conceal
pen.Conceal(true)
case 9: // Crossed-out/Strikethrough
pen.Strikethrough(true)
case 22: // Normal Intensity (not bold or faint)
pen.Bold(false).Faint(false)
case 23: // Not italic, not Fraktur
pen.Italic(false)
case 24: // Not underlined
pen.Underline(false)
case 25: // Blink off
pen.SlowBlink(false).RapidBlink(false)
case 27: // Positive (not reverse)
pen.Reverse(false)
case 28: // Reveal
pen.Conceal(false)
case 29: // Not crossed out
pen.Strikethrough(false)
case 30, 31, 32, 33, 34, 35, 36, 37: // Set foreground
pen.Foreground(ansi.Black + ansi.BasicColor(param-30)) //nolint:gosec
case 38: // Set foreground 256 or truecolor
var c color.Color
n := ReadStyleColor(params[i:], &c)
if n > 0 {
pen.Foreground(c)
i += n - 1
}
case 39: // Default foreground
pen.Foreground(nil)
case 40, 41, 42, 43, 44, 45, 46, 47: // Set background
pen.Background(ansi.Black + ansi.BasicColor(param-40)) //nolint:gosec
case 48: // Set background 256 or truecolor
var c color.Color
n := ReadStyleColor(params[i:], &c)
if n > 0 {
pen.Background(c)
i += n - 1
}
case 49: // Default Background
pen.Background(nil)
case 58: // Set underline color
var c color.Color
n := ReadStyleColor(params[i:], &c)
if n > 0 {
pen.UnderlineColor(c)
i += n - 1
}
case 59: // Default underline color
pen.UnderlineColor(nil)
case 90, 91, 92, 93, 94, 95, 96, 97: // Set bright foreground
pen.Foreground(ansi.BrightBlack + ansi.BasicColor(param-90)) //nolint:gosec
case 100, 101, 102, 103, 104, 105, 106, 107: // Set bright background
pen.Background(ansi.BrightBlack + ansi.BasicColor(param-100)) //nolint:gosec
}
}
}
// ReadLink reads a hyperlink escape sequence from a data buffer.
func ReadLink(p []byte, link *Link) {
params := bytes.Split(p, []byte{';'})
if len(params) != 3 {
return
}
link.Params = string(params[1])
link.URL = string(params[2])
}
// ReadStyleColor reads a color from a list of parameters.
// See [ansi.ReadStyleColor] for more information.
func ReadStyleColor(params ansi.Params, c *color.Color) int {
return ansi.ReadStyleColor(params, c)
}
|