diff options
-rw-r--r-- | color.c | 24 | ||||
-rw-r--r-- | color.h | 16 | ||||
-rwxr-xr-x | t/t4026-color.sh | 15 |
3 files changed, 41 insertions, 14 deletions
@@ -47,7 +47,7 @@ void color_parse_mem(const char *value, int value_len, const char *var, { const char *ptr = value; int len = value_len; - int attr = -1; + unsigned int attr = 0; int fg = -2; int bg = -2; @@ -56,7 +56,7 @@ void color_parse_mem(const char *value, int value_len, const char *var, return; } - /* [fg [bg]] [attr] */ + /* [fg [bg]] [attr]... */ while (len > 0) { const char *word = ptr; int val, wordlen = 0; @@ -85,19 +85,27 @@ void color_parse_mem(const char *value, int value_len, const char *var, goto bad; } val = parse_attr(word, wordlen); - if (val < 0 || attr != -1) + if (0 <= val) + attr |= (1 << val); + else goto bad; - attr = val; } - if (attr >= 0 || fg >= 0 || bg >= 0) { + if (attr || fg >= 0 || bg >= 0) { int sep = 0; + int i; *dst++ = '\033'; *dst++ = '['; - if (attr >= 0) { - *dst++ = '0' + attr; - sep++; + + for (i = 0; attr; i++) { + unsigned bit = (1 << i); + if (!(attr & bit)) + continue; + attr &= ~bit; + if (sep++) + *dst++ = ';'; + *dst++ = '0' + i; } if (fg >= 0) { if (sep++) @@ -1,8 +1,20 @@ #ifndef COLOR_H #define COLOR_H -/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ -#define COLOR_MAXLEN 24 +/* 2 + (2 * num_attrs) + 8 + 1 + 8 + 'm' + NUL */ +/* "\033[1;2;4;5;7;38;5;2xx;48;5;2xxm\0" */ +/* + * The maximum length of ANSI color sequence we would generate: + * - leading ESC '[' 2 + * - attr + ';' 2 * 8 (e.g. "1;") + * - fg color + ';' 9 (e.g. "38;5;2xx;") + * - fg color + ';' 9 (e.g. "48;5;2xx;") + * - terminating 'm' NUL 2 + * + * The above overcounts attr (we only use 5 not 8) and one semicolon + * but it is close enough. + */ +#define COLOR_MAXLEN 40 /* * IMPORTANT: Due to the way these color codes are emulated on Windows, diff --git a/t/t4026-color.sh b/t/t4026-color.sh index 5ade44c043..d5ccdd0cf8 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -8,14 +8,13 @@ test_description='Test diff/status color escape codes' color() { - git config diff.color.new "$1" && - test "`git config --get-color diff.color.new`" = "$2" + actual=$(git config --get-color no.such.slot "$1") && + test "$actual" = "$2" } invalid_color() { - git config diff.color.new "$1" && - test -z "`git config --get-color diff.color.new 2>/dev/null`" + test_must_fail git config --get-color no.such.slot "$1" } test_expect_success 'reset' ' @@ -42,6 +41,14 @@ test_expect_success 'fg bg attr' ' color "blue red ul" "[4;34;41m" ' +test_expect_success 'fg bg attr...' ' + color "blue bold dim ul blink reverse" "[1;2;4;5;7;34m" +' + +test_expect_success 'long color specification' ' + color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m" +' + test_expect_success '256 colors' ' color "254 bold 255" "[1;38;5;254;48;5;255m" ' |