@@ -15,45 +15,28 @@ const (
15
15
matchPosTag int = 1
16
16
matchPosValue int = 2
17
17
18
- // special values to modify 8 bit color codes
19
- fgToBgIncrement int = 10
20
- boldIncrement int = 60
21
-
22
- defaultFg int = 39
23
- defaultBg int = 49
24
-
25
18
defaultFg256 int = - 2
26
19
defaultBg256 int = - 2
27
20
28
21
posMax int = 16000
22
+
23
+ ansiResetAll = "\033 [0m"
24
+ htmlResetAll = "</span>"
29
25
)
30
26
31
27
const (
32
- // 8 bit color mode
33
- Color8 ColorMode = iota
34
28
// 256 bit color mode
35
- Color256
29
+ Color8Bit ColorMode = iota
30
+ Color24Bit
36
31
)
37
32
38
33
var (
39
34
40
35
// regular expressions
41
36
propertyRegex , _ = regexp .Compile (" (bg|fg|bold|position|clear)=[\" ']?([a-z0-9,_-]+)[\" ']?" )
42
37
43
- // map of strings to 4 bit color codes
44
- colorMap8 map [string ]int = map [string ]int {
45
- "black" : 30 ,
46
- "red" : 31 ,
47
- "green" : 32 ,
48
- "yellow" : 33 ,
49
- "blue" : 34 ,
50
- "magenta" : 35 ,
51
- "cyan" : 36 ,
52
- "white" : 37 ,
53
- }
54
-
55
38
// map of strings to 8 bit color codes
56
- colorMap256 map [string ]int = map [string ]int {
39
+ colorAliases map [string ]int = map [string ]int {
57
40
"black" : 0 ,
58
41
"red" : 1 ,
59
42
"green" : 2 ,
@@ -89,53 +72,62 @@ var (
89
72
"scrollback" : 3 ,
90
73
}
91
74
92
- colorMode ColorMode = Color8
75
+ ansiFgSeq [256 ]string
76
+ ansiBgSeq [256 ]string
93
77
94
78
rwLock = sync.RWMutex {}
95
79
)
96
80
97
81
type ansiProperties struct {
98
82
fg int
99
83
bg int
100
- bold bool
101
84
clear int
102
85
position []uint16
86
+ htmlOnly bool
103
87
}
104
88
105
89
func (p * ansiProperties ) AnsiReset () string {
106
- return " \033 [39;49m"
90
+ return ansiResetAll
107
91
}
108
92
109
93
func (p ansiProperties ) PropagateAnsiCode (previous * ansiProperties ) string {
110
94
111
95
if previous != nil {
112
- if colorMode == Color8 {
113
- if p .fg == defaultFg {
114
- p .fg = previous .fg
115
- }
116
- if p .bg == defaultBg {
117
- p .bg = previous .bg
118
- }
119
- if ! p .bold {
120
- p .bold = previous .bold
121
- }
122
- } else {
123
- if p .fg == defaultFg256 {
124
- p .fg = previous .fg
125
- }
126
- if p .bg == defaultBg256 {
127
- p .bg = previous .bg
128
- }
96
+
97
+ if p .fg == defaultFg256 {
98
+ p .fg = previous .fg
99
+ }
100
+ if p .bg == defaultBg256 {
101
+ p .bg = previous .bg
129
102
}
130
103
}
131
104
132
- if p .bold && colorMode == Color8 {
133
- if p .fg < 90 && p .fg != defaultFg {
134
- p .fg += boldIncrement
105
+ if p .htmlOnly {
106
+
107
+ if previous != nil {
108
+
109
+ if p .fg == previous .fg && p .bg == previous .bg {
110
+ return `<span>`
111
+ }
112
+ }
113
+
114
+ if p .fg == defaultFg256 && p .bg == defaultBg256 {
115
+ return `<span>`
116
+ }
117
+
118
+ htmlStr := `<span style="`
119
+
120
+ if p .fg > - 1 {
121
+ clr := RGB (p .fg )
122
+ htmlStr += `color:#` + clr .Hex + `;`
135
123
}
136
- if p .bg < 90 && p .fg != defaultBg {
137
- p .bg += boldIncrement
124
+
125
+ if p .bg > - 1 {
126
+ clr := RGB (p .bg )
127
+ htmlStr += `background-color:#` + clr .Hex + `;`
138
128
}
129
+
130
+ return htmlStr + `">`
139
131
}
140
132
141
133
var clearCode string = ""
@@ -149,29 +141,18 @@ func (p ansiProperties) PropagateAnsiCode(previous *ansiProperties) string {
149
141
}
150
142
151
143
var colorCode string = ""
152
- if colorMode == Color8 {
153
- if p .fg > - 1 || p .bg > - 1 {
154
- colorCode = "\033 ["
155
- if p .fg > - 1 {
156
- colorCode += strconv .Itoa (p .fg )
157
- if p .bg > - 1 {
158
- colorCode += ";" + strconv .Itoa (p .bg )
159
- }
160
- colorCode += "m"
161
- } else {
162
- colorCode += strconv .Itoa (p .bg ) + "m"
163
- }
164
- }
165
- } else {
166
144
145
+ if p .fg == defaultFg256 && p .bg == defaultBg256 {
146
+ colorCode = "\033 [0m"
147
+ } else {
167
148
if p .fg > - 1 {
168
- colorCode += " \033 [38;5;" + strconv . Itoa ( p .fg ) + `m`
149
+ colorCode += ansiFgSeq [ p .fg ]
169
150
} else if p .fg == defaultFg256 {
170
151
colorCode += "\033 [39m"
171
152
}
172
153
173
154
if p .bg > - 1 {
174
- colorCode += " \033 [48;5;" + strconv . Itoa ( p .bg ) + `m`
155
+ colorCode += ansiBgSeq [ p .bg ]
175
156
} else if p .bg == defaultBg256 {
176
157
colorCode += "\033 [49m"
177
158
}
@@ -181,77 +162,37 @@ func (p ansiProperties) PropagateAnsiCode(previous *ansiProperties) string {
181
162
}
182
163
183
164
func SetColorMode (mode ColorMode ) {
184
- colorMode = mode
185
- }
186
-
187
- func AnsiResetAll () string {
188
- return "\033 [0m"
165
+ // This is a NOOP now, left for backwards compatibility
189
166
}
190
167
191
168
func extractProperties (tagStr string ) * ansiProperties {
192
169
193
- var ret * ansiProperties
194
-
195
- if colorMode == Color8 {
196
- ret = & ansiProperties {fg : defaultFg , bg : defaultBg , clear : - 1 }
197
- } else {
198
- ret = & ansiProperties {fg : defaultFg256 , bg : defaultBg256 , clear : - 1 }
199
- }
170
+ var ret = & ansiProperties {fg : defaultFg256 , bg : defaultBg256 , clear : - 1 }
200
171
201
172
result := propertyRegex .FindAllStringSubmatch (tagStr , - 1 )
202
173
var err error
203
174
var colorVal int
204
- var aliasFound bool
175
+ var ok bool
205
176
for _ , match := range result {
206
177
207
178
switch match [matchPosTag ] {
208
179
case "fg" :
209
180
if ret .fg , err = strconv .Atoi (match [matchPosValue ]); err != nil {
210
181
211
- if colorMode == Color8 {
212
- colorVal , aliasFound = colorMap8 [match [matchPosValue ]]
213
- } else {
214
- colorVal , aliasFound = colorMap256 [match [matchPosValue ]]
215
- }
216
-
217
- if aliasFound {
182
+ if colorVal , ok = colorAliases [match [matchPosValue ]]; ok {
218
183
ret .fg = colorVal
219
184
} else {
220
- if colorMode == Color8 {
221
- ret .fg = defaultFg
222
- } else {
223
- ret .fg = defaultFg256
224
- }
185
+ ret .fg = defaultFg256
225
186
}
226
-
227
187
}
228
188
case "bg" :
229
189
if ret .bg , err = strconv .Atoi (match [matchPosValue ]); err != nil {
230
190
231
- if colorMode == Color8 {
232
- colorVal , aliasFound = colorMap8 [match [matchPosValue ]]
233
- colorVal += 10
234
- } else {
235
- colorVal , aliasFound = colorMap256 [match [matchPosValue ]]
236
- }
237
-
238
- if aliasFound {
191
+ if colorVal , ok = colorAliases [match [matchPosValue ]]; ok {
239
192
ret .bg = colorVal
240
193
} else {
241
- if colorMode == Color8 {
242
- ret .bg = defaultBg
243
- } else {
244
- ret .bg = defaultBg256
245
- }
194
+ ret .bg = defaultBg256
246
195
}
247
-
248
- }
249
- case "bold" :
250
- if colorMode != Color8 {
251
- continue
252
- }
253
- if ret .bold , err = strconv .ParseBool (match [matchPosValue ]); err != nil {
254
- ret .bold = false
255
196
}
256
197
case "position" :
257
198
@@ -282,9 +223,16 @@ func extractProperties(tagStr string) *ansiProperties {
282
223
ret .clear = val
283
224
}
284
225
}
285
- //fmt.Printf("%#v = %#v\n", val[matchPosTag], val[matchPosValue])
286
226
287
227
}
288
228
289
229
return ret
290
230
}
231
+
232
+ // Speed up by pre-computing these values
233
+ func init () {
234
+ for i := 0 ; i < 256 ; i ++ {
235
+ ansiFgSeq [i ] = "\033 [38;5;" + strconv .Itoa (i ) + "m"
236
+ ansiBgSeq [i ] = "\033 [48;5;" + strconv .Itoa (i ) + "m"
237
+ }
238
+ }
0 commit comments