Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added 256-color xterm-style ANSI code support, e.g. ESC[38;5;121m. Ad…

…ded tests for same, as well as some more tests for existing ANSI color codes.
  • Loading branch information...
commit d6545d983c5c0782c5a97a4ebd9821e9acfe10f7 1 parent 3f78401
Tyler Berry authored
22 filters/J3ANSIFormattingFilter.h
@@ -35,6 +35,7 @@ typedef enum J3ANSICode
35 35 J3ANSIForegroundMagenta = 35,
36 36 J3ANSIForegroundCyan = 36,
37 37 J3ANSIForegroundWhite = 37,
  38 + J3ANSIForeground256 = 38,
38 39 J3ANSIForegroundDefault = 39,
39 40 J3ANSIBackgroundBlack = 40,
40 41 J3ANSIBackgroundRed = 41,
@@ -44,9 +45,30 @@ typedef enum J3ANSICode
44 45 J3ANSIBackgroundMagenta = 45,
45 46 J3ANSIBackgroundCyan = 46,
46 47 J3ANSIBackgroundWhite = 47,
  48 + J3ANSIBackground256 = 48,
47 49 J3ANSIBackgroundDefault = 49
48 50 } J3ANSICode;
49 51
  52 +typedef enum J3ANSI256ColorCode
  53 +{
  54 + J3ANSI256Black = 0,
  55 + J3ANSI256Red = 1,
  56 + J3ANSI256Green = 2,
  57 + J3ANSI256Yellow = 3,
  58 + J3ANSI256Blue = 4,
  59 + J3ANSI256Magenta = 5,
  60 + J3ANSI256Cyan = 6,
  61 + J3ANSI256White = 7,
  62 + J3ANSI256BrightBlack = 8,
  63 + J3ANSI256BrightRed = 9,
  64 + J3ANSI256BrightGreen = 10,
  65 + J3ANSI256BrightYellow = 11,
  66 + J3ANSI256BrightBlue = 12,
  67 + J3ANSI256BrightMagenta = 13,
  68 + J3ANSI256BrightCyan = 14,
  69 + J3ANSI256BrightWhite = 15,
  70 +} J3ANSI256ColorCode;
  71 +
50 72 @interface J3ANSIFormattingFilter : J3Filter
51 73 {
52 74 BOOL inCode;
94 filters/J3ANSIFormattingFilter.m
@@ -92,6 +92,21 @@ - (NSArray *) attributeNamesForANSICode
92 92 NSArray *codeComponents = [[ansiCode substringFromIndex: 2] componentsSeparatedByString: @";"];
93 93 NSMutableArray *names = [NSMutableArray arrayWithCapacity: [codeComponents count]];
94 94
  95 + if ([codeComponents count] == 3
  96 + && [[codeComponents objectAtIndex: 1] intValue] == 5)
  97 + {
  98 + if ([[codeComponents objectAtIndex: 0] intValue] == J3ANSIBackground256)
  99 + {
  100 + [names addObject: NSBackgroundColorAttributeName];
  101 + return names;
  102 + }
  103 + else if ([[codeComponents objectAtIndex: 0] intValue] == J3ANSIForeground256)
  104 + {
  105 + [names addObject: NSForegroundColorAttributeName];
  106 + return names;
  107 + }
  108 + }
  109 +
95 110 for (NSString *code in codeComponents)
96 111 {
97 112 switch ([code intValue])
@@ -144,6 +159,85 @@ - (NSArray *) attributeValuesForANSICodeInString: (NSAttributedString *) string
144 159 NSArray *codeComponents = [[ansiCode substringFromIndex: 2] componentsSeparatedByString: @";"];
145 160 NSMutableArray *values = [NSMutableArray arrayWithCapacity: [codeComponents count]];
146 161
  162 + if ([codeComponents count] == 3
  163 + && [[codeComponents objectAtIndex: 1] intValue] == 5)
  164 + {
  165 + if ([[codeComponents objectAtIndex: 0] intValue] == J3ANSIBackground256
  166 + || [[codeComponents objectAtIndex: 0] intValue] == J3ANSIForeground256)
  167 + {
  168 + int value = [[codeComponents objectAtIndex: 2] intValue];
  169 +
  170 + if (value < 16)
  171 + {
  172 + switch (value)
  173 + {
  174 + case J3ANSI256Black:
  175 + case J3ANSI256BrightBlack:
  176 + [values addObject: [NSColor darkGrayColor]];
  177 + break;
  178 +
  179 + case J3ANSI256Red:
  180 + case J3ANSI256BrightRed:
  181 + [values addObject: [NSColor redColor]];
  182 + break;
  183 +
  184 + case J3ANSI256Green:
  185 + case J3ANSI256BrightGreen:
  186 + [values addObject: [NSColor greenColor]];
  187 + break;
  188 +
  189 + case J3ANSI256Yellow:
  190 + case J3ANSI256BrightYellow:
  191 + [values addObject: [NSColor yellowColor]];
  192 + break;
  193 +
  194 + case J3ANSI256Blue:
  195 + case J3ANSI256BrightBlue:
  196 + [values addObject: [NSColor blueColor]];
  197 + break;
  198 +
  199 + case J3ANSI256Magenta:
  200 + case J3ANSI256BrightMagenta:
  201 + [values addObject: [NSColor magentaColor]];
  202 + break;
  203 +
  204 + case J3ANSI256Cyan:
  205 + case J3ANSI256BrightCyan:
  206 + [values addObject: [NSColor cyanColor]];
  207 + break;
  208 +
  209 + case J3ANSI256White:
  210 + case J3ANSI256BrightWhite:
  211 + [values addObject: [NSColor whiteColor]];
  212 + break;
  213 + }
  214 + }
  215 + else if (value > 15 && value < 232)
  216 + {
  217 + int adjustedValue = value - 16;
  218 + int red = adjustedValue / 36;
  219 + int green = (adjustedValue % 36) / 6;
  220 + int blue = (adjustedValue % 36) % 6;
  221 +
  222 + NSColor *cubeColor = [NSColor colorWithCalibratedRed: 1. / 6. * red
  223 + green: 1. / 6. * green
  224 + blue: 1. / 6. * blue
  225 + alpha: 1.0];
  226 + [values addObject: cubeColor];
  227 + }
  228 + else if (value > 231 && value < 256)
  229 + {
  230 + int adjustedValue = value - 231;
  231 +
  232 + NSColor *grayscaleColor = [NSColor colorWithCalibratedWhite: 1. / 25. * adjustedValue
  233 + alpha: 1.0];
  234 + [values addObject: grayscaleColor];
  235 + }
  236 +
  237 + return values;
  238 + }
  239 + }
  240 +
147 241 for (NSString *code in codeComponents)
148 242 {
149 243 switch ([code intValue])
202 tests/J3ANSIFormattingFilterTests.m
@@ -204,6 +204,107 @@ - (void) testForegroundColor
204 204 [self assertString: output hasValue: [J3Formatter testingForeground] forAttribute: NSForegroundColorAttributeName atIndex: 4 message: @"e"];
205 205 }
206 206
  207 +- (void) testStandardForegroundColors
  208 +{
  209 + NSAttributedString *input = [self constructAttributedStringForString: @"\x1B[30ma\x1B[31mb\x1B[32mc\x1B[33md\x1B[34me\x1B[35mf\x1B[36mg\x1B[37mh"];
  210 + NSAttributedString *output = [queue processAttributedString: input];
  211 +
  212 + [self assertString: output hasValue: [NSColor darkGrayColor] forAttribute: NSForegroundColorAttributeName atIndex: 0 message: @"a"];
  213 + [self assertString: output hasValue: [NSColor redColor] forAttribute: NSForegroundColorAttributeName atIndex: 1 message: @"b"];
  214 + [self assertString: output hasValue: [NSColor greenColor] forAttribute: NSForegroundColorAttributeName atIndex: 2 message: @"c"];
  215 + [self assertString: output hasValue: [NSColor yellowColor] forAttribute: NSForegroundColorAttributeName atIndex: 3 message: @"d"];
  216 + [self assertString: output hasValue: [NSColor blueColor] forAttribute: NSForegroundColorAttributeName atIndex: 4 message: @"e"];
  217 + [self assertString: output hasValue: [NSColor magentaColor] forAttribute: NSForegroundColorAttributeName atIndex: 5 message: @"f"];
  218 + [self assertString: output hasValue: [NSColor cyanColor] forAttribute: NSForegroundColorAttributeName atIndex: 6 message: @"g"];
  219 + [self assertString: output hasValue: [NSColor whiteColor] forAttribute: NSForegroundColorAttributeName atIndex: 7 message: @"h"];
  220 +}
  221 +
  222 +- (void) testXTerm256ForegroundColor
  223 +{
  224 + for (unsigned i = 0; i < 16; i++)
  225 + {
  226 + NSAttributedString *input = [self constructAttributedStringForString: [NSString stringWithFormat: @"\x1B[38;5;%dm%d", i, i]];
  227 + NSAttributedString *output = [queue processAttributedString: input];
  228 +
  229 + NSColor *targetColor;
  230 +
  231 + switch (i)
  232 + {
  233 + case J3ANSI256Black:
  234 + case J3ANSI256BrightBlack:
  235 + targetColor = [NSColor darkGrayColor];
  236 + break;
  237 +
  238 + case J3ANSI256Red:
  239 + case J3ANSI256BrightRed:
  240 + targetColor = [NSColor redColor];
  241 + break;
  242 +
  243 + case J3ANSI256Green:
  244 + case J3ANSI256BrightGreen:
  245 + targetColor = [NSColor greenColor];
  246 + break;
  247 +
  248 + case J3ANSI256Yellow:
  249 + case J3ANSI256BrightYellow:
  250 + targetColor = [NSColor yellowColor];
  251 + break;
  252 +
  253 + case J3ANSI256Blue:
  254 + case J3ANSI256BrightBlue:
  255 + targetColor = [NSColor blueColor];
  256 + break;
  257 +
  258 + case J3ANSI256Magenta:
  259 + case J3ANSI256BrightMagenta:
  260 + targetColor = [NSColor magentaColor];
  261 + break;
  262 +
  263 + case J3ANSI256Cyan:
  264 + case J3ANSI256BrightCyan:
  265 + targetColor = [NSColor cyanColor];
  266 + break;
  267 +
  268 + case J3ANSI256White:
  269 + case J3ANSI256BrightWhite:
  270 + targetColor = [NSColor whiteColor];
  271 + }
  272 +
  273 + [self assertString: output hasValue: targetColor forAttribute: NSForegroundColorAttributeName atIndex: 0 message: [NSString stringWithFormat: @"%d", i]];
  274 + }
  275 +
  276 + for (unsigned i = 16; i < 232; i++)
  277 + {
  278 + NSAttributedString *input = [self constructAttributedStringForString: [NSString stringWithFormat: @"\x1B[38;5;%dm%d", i, i]];
  279 + NSAttributedString *output = [queue processAttributedString: input];
  280 +
  281 + int adjustedValue = i - 16;
  282 + int red = adjustedValue / 36;
  283 + int green = (adjustedValue % 36) / 6;
  284 + int blue = (adjustedValue % 36) % 6;
  285 +
  286 + NSColor *cubeColor = [NSColor colorWithCalibratedRed: 1. / 6. * red
  287 + green: 1. / 6. * green
  288 + blue: 1. / 6. * blue
  289 + alpha: 1.0];
  290 +
  291 + [self assertString: output hasValue: cubeColor forAttribute: NSForegroundColorAttributeName atIndex: 0 message: [NSString stringWithFormat: @"%d", i]];
  292 + }
  293 +
  294 + for (unsigned i = 232; i < 256; i++)
  295 + {
  296 + NSAttributedString *input = [self constructAttributedStringForString: [NSString stringWithFormat: @"\x1B[38;5;%dm%d", i, i]];
  297 + NSAttributedString *output = [queue processAttributedString: input];
  298 +
  299 + int adjustedValue = i - 231;
  300 +
  301 + NSColor *grayscaleColor = [NSColor colorWithCalibratedWhite: 1. / 25. * adjustedValue
  302 + alpha: 1.0];
  303 +
  304 + [self assertString: output hasValue: grayscaleColor forAttribute: NSForegroundColorAttributeName atIndex: 0 message: [NSString stringWithFormat: @"%d", i]];
  305 + }
  306 +}
  307 +
207 308 - (void) testBackgroundColor
208 309 {
209 310 NSAttributedString *input = [self constructAttributedStringForString: @"a\x1B[46mbc\x1B[45md\x1B[49me"];
@@ -216,6 +317,107 @@ - (void) testBackgroundColor
216 317 [self assertString: output hasValue: [J3Formatter testingBackground] forAttribute: NSBackgroundColorAttributeName atIndex: 4 message: @"e"];
217 318 }
218 319
  320 +- (void) testStandardBackgroundColors
  321 +{
  322 + NSAttributedString *input = [self constructAttributedStringForString: @"\x1B[40ma\x1B[41mb\x1B[42mc\x1B[43md\x1B[44me\x1B[45mf\x1B[46mg\x1B[47mh"];
  323 + NSAttributedString *output = [queue processAttributedString: input];
  324 +
  325 + [self assertString: output hasValue: [NSColor darkGrayColor] forAttribute: NSBackgroundColorAttributeName atIndex: 0 message: @"a"];
  326 + [self assertString: output hasValue: [NSColor redColor] forAttribute: NSBackgroundColorAttributeName atIndex: 1 message: @"b"];
  327 + [self assertString: output hasValue: [NSColor greenColor] forAttribute: NSBackgroundColorAttributeName atIndex: 2 message: @"c"];
  328 + [self assertString: output hasValue: [NSColor yellowColor] forAttribute: NSBackgroundColorAttributeName atIndex: 3 message: @"d"];
  329 + [self assertString: output hasValue: [NSColor blueColor] forAttribute: NSBackgroundColorAttributeName atIndex: 4 message: @"e"];
  330 + [self assertString: output hasValue: [NSColor magentaColor] forAttribute: NSBackgroundColorAttributeName atIndex: 5 message: @"f"];
  331 + [self assertString: output hasValue: [NSColor cyanColor] forAttribute: NSBackgroundColorAttributeName atIndex: 6 message: @"g"];
  332 + [self assertString: output hasValue: [NSColor whiteColor] forAttribute: NSBackgroundColorAttributeName atIndex: 7 message: @"h"];
  333 +}
  334 +
  335 +- (void) testXTerm256BackgroundColor
  336 +{
  337 + for (unsigned i = 0; i < 16; i++)
  338 + {
  339 + NSAttributedString *input = [self constructAttributedStringForString: [NSString stringWithFormat: @"\x1B[48;5;%dm%d", i, i]];
  340 + NSAttributedString *output = [queue processAttributedString: input];
  341 +
  342 + NSColor *targetColor;
  343 +
  344 + switch (i)
  345 + {
  346 + case J3ANSI256Black:
  347 + case J3ANSI256BrightBlack:
  348 + targetColor = [NSColor darkGrayColor];
  349 + break;
  350 +
  351 + case J3ANSI256Red:
  352 + case J3ANSI256BrightRed:
  353 + targetColor = [NSColor redColor];
  354 + break;
  355 +
  356 + case J3ANSI256Green:
  357 + case J3ANSI256BrightGreen:
  358 + targetColor = [NSColor greenColor];
  359 + break;
  360 +
  361 + case J3ANSI256Yellow:
  362 + case J3ANSI256BrightYellow:
  363 + targetColor = [NSColor yellowColor];
  364 + break;
  365 +
  366 + case J3ANSI256Blue:
  367 + case J3ANSI256BrightBlue:
  368 + targetColor = [NSColor blueColor];
  369 + break;
  370 +
  371 + case J3ANSI256Magenta:
  372 + case J3ANSI256BrightMagenta:
  373 + targetColor = [NSColor magentaColor];
  374 + break;
  375 +
  376 + case J3ANSI256Cyan:
  377 + case J3ANSI256BrightCyan:
  378 + targetColor = [NSColor cyanColor];
  379 + break;
  380 +
  381 + case J3ANSI256White:
  382 + case J3ANSI256BrightWhite:
  383 + targetColor = [NSColor whiteColor];
  384 + }
  385 +
  386 + [self assertString: output hasValue: targetColor forAttribute: NSBackgroundColorAttributeName atIndex: 0 message: [NSString stringWithFormat: @"%d", i]];
  387 + }
  388 +
  389 + for (unsigned i = 16; i < 232; i++)
  390 + {
  391 + NSAttributedString *input = [self constructAttributedStringForString: [NSString stringWithFormat: @"\x1B[48;5;%dm%d", i, i]];
  392 + NSAttributedString *output = [queue processAttributedString: input];
  393 +
  394 + int adjustedValue = i - 16;
  395 + int red = adjustedValue / 36;
  396 + int green = (adjustedValue % 36) / 6;
  397 + int blue = (adjustedValue % 36) % 6;
  398 +
  399 + NSColor *cubeColor = [NSColor colorWithCalibratedRed: 1. / 6. * red
  400 + green: 1. / 6. * green
  401 + blue: 1. / 6. * blue
  402 + alpha: 1.0];
  403 +
  404 + [self assertString: output hasValue: cubeColor forAttribute: NSBackgroundColorAttributeName atIndex: 0 message: [NSString stringWithFormat: @"%d", i]];
  405 + }
  406 +
  407 + for (unsigned i = 232; i < 256; i++)
  408 + {
  409 + NSAttributedString *input = [self constructAttributedStringForString: [NSString stringWithFormat: @"\x1B[48;5;%dm%d", i, i]];
  410 + NSAttributedString *output = [queue processAttributedString: input];
  411 +
  412 + int adjustedValue = i - 231;
  413 +
  414 + NSColor *grayscaleColor = [NSColor colorWithCalibratedWhite: 1. / 25. * adjustedValue
  415 + alpha: 1.0];
  416 +
  417 + [self assertString: output hasValue: grayscaleColor forAttribute: NSBackgroundColorAttributeName atIndex: 0 message: [NSString stringWithFormat: @"%d", i]];
  418 + }
  419 +}
  420 +
219 421 - (void) testForegroundAndBackgroundColorAsCompoundCode
220 422 {
221 423 NSAttributedString *input = [self constructAttributedStringForString: @"a\x1B[36;46mbc\x1B[45;35md\x1B[39;49me"];

0 comments on commit d6545d9

Please sign in to comment.
Something went wrong with that request. Please try again.