@@ -63,49 +63,129 @@ class ColorParser implements IReader<StringTokenValue> {
63
63
64
64
ColorToken _consumeStyleToken (ColorToken token) {
65
65
// print('Consuming style token for $token');
66
- final color = _consumeUntil ('m' );
66
+ final args = _consumeUntil ('m' );
67
67
reader.read ();
68
+ token = _parseStyleToken (token, args.split (';' ));
69
+ return token;
70
+ }
68
71
69
- if (! color.contains (';' )) {
70
- //single number color [30-37] / [40-47]
71
- // or [90-97] / [100-107], fg / bg
72
- // e.g. ^[40m
73
- // or just style ? e.g. ^[1m
74
-
75
- // TODO: this seems to crash on ^[40m, don't understand exactly why
76
- // doesn't seem to be the 40m, that one gets interpreted well (black bg)
77
-
78
- int colorValue = - 1 ;
79
- try {
80
- colorValue = int .parse (color);
81
- } on FormatException {
82
- // ignore, then??
83
- // print("failing color= " + color);
84
- // TODO: it keeps logging thousands of empty "failing colors" ?
85
- }
86
- if (colorValue > - 1 ) { // init safely, ignore if nothing ?
87
- if ((30 <= colorValue) && (colorValue <= 37 ) ||
88
- (90 <= colorValue) && (colorValue <= 97 )) {
89
- token.fgColor = colorValue;
90
- } else if ((40 <= colorValue) && (colorValue <= 47 ) ||
91
- (100 <= colorValue) && (colorValue <= 107 )) {
92
- token.bgColor = colorValue;
93
- } else if (colorValue < 30 ) { // style ?
94
- token.setStyle (colorValue);
72
+ ColorToken _parseStyleToken (ColorToken token, List <String > colors) {
73
+ final colorNums = colors.map ((n) => int .parse (n)).toList ();
74
+ // Special cases
75
+ if (_checkPair (colorNums, 38 , 2 ) || _checkPair (colors, 48 , 2 )) {
76
+ // RGB format is 38;2;R;G;B or 48;2;R;G;B
77
+ token = _consumeRgbToken (token, colors);
78
+ colors.removeRange (0 , 5 );
79
+ } else if (_checkPair (colorNums, 38 , 5 ) || _checkPair (colorNums, 48 , 5 )) {
80
+ // Xterm256 format is 38;5;N or 48;5;N
81
+ token = _consumeXterm256Token (token, colors);
82
+ colors.removeRange (0 , 3 );
83
+ } else {
84
+ // Other style codes
85
+ for (var color in colorNums) {
86
+ if (color < 30 ) {
87
+ token.setStyle (color);
88
+ } else if (_checkBetween (color, 30 , 37 ) ||
89
+ _checkBetween (color, 90 , 97 )) {
90
+ token.fgColor = color;
91
+ if (_checkBetween (color, 90 , 97 )) {
92
+ token.brightFg = true ;
93
+ }
94
+ } else if (_checkBetween (color, 40 , 47 ) ||
95
+ _checkBetween (color, 100 , 107 )) {
96
+ token.bgColor = color;
97
+ if (_checkBetween (color, 100 , 107 )) {
98
+ token.brightBg = true ;
99
+ }
95
100
}
101
+ colors.removeAt (0 );
96
102
}
97
103
}
98
- // things like ^[1;38;2;114;150;50;48;2;125;70;22m TEXT ^[0m
99
- else { // multi number madness, trying recursive parser ?
100
- final colors = color.split (';' );
101
- processTokenStyle (colors, token); //really hope this works by reference
104
+
105
+ if (colors.isNotEmpty) {
106
+ token = _parseStyleToken (token, colors);
102
107
}
103
- if (reader.peek () == Consts .esc) {
104
- return _consumeEscSequence (token);
108
+
109
+ return token;
110
+ }
111
+
112
+ ColorToken _consumeRgbToken (ColorToken token, List <String > colors) {
113
+ final rgb = '${colors [2 ]};${colors [3 ]};${colors [4 ]}' ;
114
+ if (colors[0 ] == '38' ) {
115
+ token.rgbFg = true ;
116
+ token.rgbFgColor = rgb;
117
+ } else if (colors[0 ] == '48' ) {
118
+ token.rgbBg = true ;
119
+ token.rgbBgColor = rgb;
120
+ }
121
+ return token;
122
+ }
123
+
124
+ ColorToken _consumeXterm256Token (ColorToken token, List <String > colors) {
125
+ final color = int .parse (colors[2 ]);
126
+ if (colors[0 ] == '38' ) {
127
+ token.xterm256 = true ;
128
+ token.fgColor = color;
129
+ } else if (colors[0 ] == '48' ) {
130
+ token.xterm256 = true ;
131
+ token.bgColor = color;
105
132
}
106
133
return token;
107
134
}
108
135
136
+ bool _checkPair <T >(List <T > arr, T v1, T v2) {
137
+ return arr.length > 1 && arr[0 ] == v1 && arr[1 ] == v2;
138
+ }
139
+
140
+ bool _checkBetween <T extends num >(T value, T min, T max) {
141
+ return min <= value && value <= max;
142
+ }
143
+
144
+ // ColorToken _consumeStyleToken(ColorToken token) {
145
+ // // print('Consuming style token for $token');
146
+ // final color = _consumeUntil('m');
147
+ // reader.read();
148
+ //
149
+ // if (!color.contains(';')) {
150
+ // //single number color [30-37] / [40-47]
151
+ // // or [90-97] / [100-107], fg / bg
152
+ // // e.g. ^[40m
153
+ // // or just style ? e.g. ^[1m
154
+ //
155
+ // // TODO: this seems to crash on ^[40m, don't understand exactly why
156
+ // // doesn't seem to be the 40m, that one gets interpreted well (black bg)
157
+ //
158
+ // int colorValue = -1;
159
+ // try {
160
+ // colorValue = int.parse(color);
161
+ // } on FormatException {
162
+ // // ignore, then??
163
+ // // print("failing color= " + color);
164
+ // // TODO: it keeps logging thousands of empty "failing colors" ?
165
+ // }
166
+ // if (colorValue > -1) { // init safely, ignore if nothing ?
167
+ // if ((30 <= colorValue) && (colorValue <= 37) ||
168
+ // (90 <= colorValue) && (colorValue <= 97)) {
169
+ // token.fgColor = colorValue;
170
+ // } else if ((40 <= colorValue) && (colorValue <= 47) ||
171
+ // (100 <= colorValue) && (colorValue <= 107)) {
172
+ // token.bgColor = colorValue;
173
+ // } else if (colorValue < 30) { // style ?
174
+ // token.setStyle(colorValue);
175
+ // }
176
+ // }
177
+ // }
178
+ // // things like ^[1;38;2;114;150;50;48;2;125;70;22m TEXT ^[0m
179
+ // else { // multi number madness, trying recursive parser ?
180
+ // final colors = color.split(';');
181
+ // processTokenStyle(colors, token); //really hope this works by reference
182
+ // }
183
+ // if (reader.peek() == Consts.esc) {
184
+ // return _consumeEscSequence(token);
185
+ // }
186
+ // return token;
187
+ // }
188
+
109
189
ColorToken _consumeText (ColorToken token) {
110
190
// print('Consuming text for $token');
111
191
token.text += _consumeUntil (Consts .esc);
@@ -155,62 +235,69 @@ class ColorParser implements IReader<StringTokenValue> {
155
235
return result;
156
236
}
157
237
158
- processTokenStyle (List <String > colors, ColorToken token){
159
- if (colors.isNotEmpty) { //if it's already empty, do nothing more
160
- int first = int .parse (colors[0 ]);
161
- if (first < 30 ) { // bold, underline, etc?
162
- token.setStyle (first);
163
- colors.removeAt (0 );
164
- } else if ((30 <= first) && (first <= 37 ) || (90 <= first) && (first <= 97 ) ||
165
- (40 <= first) && (first <= 47 ) || (100 <= first) && (first <= 107 )){
166
- if ((30 <= first) && (first <= 37 ) || (90 <= first) && (first <= 97 )) {
167
- token.fgColor = first ;
168
- colors.removeAt (0 );
169
- }else if ((40 <= first) && (first <= 47 ) || (100 <= first) && (first <= 107 )) {
170
- token.bgColor = first;
171
- colors.removeAt (0 );
172
- }
173
- }else {
174
- int second = int .parse (colors[1 ]);
175
- if (first == 38 && second == 5 ) {
176
- token.xterm256 = true ;
177
- int third = int .parse (colors[2 ]);
178
- token.fgColor = third;
179
- colors.removeRange (0 , 3 );
180
- // bg = 0;
181
- } else if (first == 48 && second == 5 ) {
182
- token.xterm256 = true ;
183
- int third = int .parse (colors[2 ]);
184
- token.bgColor = third;
185
- colors.removeRange (0 , 3 );
186
- // bg = 0;
187
- } else {
188
- if (first == 38 && second == 2 ) { //rgb
189
- String red = colors[2 ];
190
- String green = colors[3 ];
191
- String blue = colors[4 ];
192
- token.rgbFg = true ;
193
- token.rgbFgColor = "$red ;$green ;$blue " ;
194
- colors.removeRange (0 , 5 );
195
- } else if (first == 48 && second == 2 ) { //rgb
196
- String red = colors[2 ];
197
- String green = colors[3 ];
198
- String blue = colors[4 ];
199
- token.rgbBg = true ;
200
- token.rgbBgColor = "$red ;$green ;$blue " ;
201
- colors.removeRange (0 , 5 );
202
- }
203
- else {
204
- return ;
205
- }
206
- }
207
- }
208
- //pass the rest of the color codes, hope for the best
209
- if (colors.isNotEmpty) {
210
- processTokenStyle (colors, token); // really really hoping these go by reference
211
- }
212
- }
213
- }
238
+ // processTokenStyle(List<String> colors, ColorToken token) {
239
+ // if (colors.isNotEmpty) {
240
+ // //if it's already empty, do nothing more
241
+ // int first = int.parse(colors[0]);
242
+ // if (first < 30) {
243
+ // // bold, underline, etc?
244
+ // token.setStyle(first);
245
+ // colors.removeAt(0);
246
+ // } else if ((30 <= first) && (first <= 37) ||
247
+ // (90 <= first) && (first <= 97) ||
248
+ // (40 <= first) && (first <= 47) ||
249
+ // (100 <= first) && (first <= 107)) {
250
+ // if ((30 <= first) && (first <= 37) || (90 <= first) && (first <= 97)) {
251
+ // token.fgColor = first;
252
+ // colors.removeAt(0);
253
+ // } else if ((40 <= first) && (first <= 47) ||
254
+ // (100 <= first) && (first <= 107)) {
255
+ // token.bgColor = first;
256
+ // colors.removeAt(0);
257
+ // }
258
+ // } else {
259
+ // int second = int.parse(colors[1]);
260
+ // if (first == 38 && second == 5) {
261
+ // token.xterm256 = true;
262
+ // int third = int.parse(colors[2]);
263
+ // token.fgColor = third;
264
+ // colors.removeRange(0, 3);
265
+ // // bg = 0;
266
+ // } else if (first == 48 && second == 5) {
267
+ // token.xterm256 = true;
268
+ // int third = int.parse(colors[2]);
269
+ // token.bgColor = third;
270
+ // colors.removeRange(0, 3);
271
+ // // bg = 0;
272
+ // } else {
273
+ // if (first == 38 && second == 2) {
274
+ // //rgb
275
+ // String red = colors[2];
276
+ // String green = colors[3];
277
+ // String blue = colors[4];
278
+ // token.rgbFg = true;
279
+ // token.rgbFgColor = "$red;$green;$blue";
280
+ // colors.removeRange(0, 5);
281
+ // } else if (first == 48 && second == 2) {
282
+ // //rgb
283
+ // String red = colors[2];
284
+ // String green = colors[3];
285
+ // String blue = colors[4];
286
+ // token.rgbBg = true;
287
+ // token.rgbBgColor = "$red;$green;$blue";
288
+ // colors.removeRange(0, 5);
289
+ // } else {
290
+ // return;
291
+ // }
292
+ // }
293
+ // }
294
+ // //pass the rest of the color codes, hope for the best
295
+ // if (colors.isNotEmpty) {
296
+ // processTokenStyle(
297
+ // colors, token); // really really hoping these go by reference
298
+ // }
299
+ // }
300
+ // }
214
301
215
302
// ignore: unused_element
216
303
_debugString (String string) => string.replaceAll ('\x 1B' , '\\ x1B' );
0 commit comments