color: allow multiple attributes
In configuration files (and "git config --color" command line), we supported one and only one attribute after foreground and background color. Accept combinations of attributes, e.g. [diff.color] old = red reverse bold Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Feb 27, 2010 at 18:56 UTC
8b124135a97b593d50a90abcec231552b31c7ade
3 files changed
+41
-14
color.c
+16
-8
@@ -49,7 +49,7 @@ void color_parse_mem(const char *value, int value_len, const char *var,
49
{
50
const char *ptr = value;
51
int len = value_len;
52
- int attr = -1;
52
+ unsigned int attr = 0;
53
int fg = -2;
54
int bg = -2;
55
@@ -58,7 +58,7 @@ void color_parse_mem(const char *value, int value_len, const char *var,
58
return;
59
}
60
61
- /* [fg [bg]] [attr] */
61
+ /* [fg [bg]] [attr]... */
62
while (len > 0) {
63
const char *word = ptr;
64
int val, wordlen = 0;
@@ -87,19 +87,27 @@ void color_parse_mem(const char *value, int value_len, const char *var,
87
goto bad;
88
}
89
val = parse_attr(word, wordlen);
90
- if (val < 0 || attr != -1)
90
+ if (0 <= val)
91
+ attr |= (1 << val);
92
+ else
93
goto bad;
92
- attr = val;
94
}
95
95
- if (attr >= 0 || fg >= 0 || bg >= 0) {
96
+ if (attr || fg >= 0 || bg >= 0) {
97
int sep = 0;
98
+ int i;
99
100
*dst++ = '\033';
101
*dst++ = '[';
100
- if (attr >= 0) {
101
- *dst++ = '0' + attr;
102
- sep++;
102
+
103
+ for (i = 0; attr; i++) {
104
+ unsigned bit = (1 << i);
105
+ if (!(attr & bit))
106
+ continue;
107
+ attr &= ~bit;
108
+ if (sep++)
109
+ *dst++ = ';';
110
+ *dst++ = '0' + i;
111
}
112
if (fg >= 0) {
113
if (sep++)
color.h
+14
-2
@@ -1,8 +1,20 @@
1
#ifndef COLOR_H
2
#define COLOR_H
3
4
-/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
5
-#define COLOR_MAXLEN 24
4
+/* 2 + (2 * num_attrs) + 8 + 1 + 8 + 'm' + NUL */
5
+/* "\033[1;2;4;5;7;38;5;2xx;48;5;2xxm\0" */
6
+/*
7
+ * The maximum length of ANSI color sequence we would generate:
8
+ * - leading ESC '[' 2
9
+ * - attr + ';' 2 * 8 (e.g. "1;")
10
+ * - fg color + ';' 9 (e.g. "38;5;2xx;")
11
+ * - fg color + ';' 9 (e.g. "48;5;2xx;")
12
+ * - terminating 'm' NUL 2
13
+ *
14
+ * The above overcounts attr (we only use 5 not 8) and one semicolon
15
+ * but it is close enough.
16
+ */
17
+#define COLOR_MAXLEN 40
18
19
/*
20
* This variable stores the value of color.ui
t/t4026-color.sh
+11
-4
@@ -8,14 +8,13 @@ test_description='Test diff/status color escape codes'
8
9
color()
10
{
11
- git config diff.color.new "$1" &&
12
- test "`git config --get-color diff.color.new`" = "$2"
11
+ actual=$(git config --get-color no.such.slot "$1") &&
12
+ test "$actual" = "$2"
13
}
14
15
invalid_color()
16
{
17
- git config diff.color.new "$1" &&
18
- test -z "`git config --get-color diff.color.new 2>/dev/null`"
17
+ test_must_fail git config --get-color no.such.slot "$1"
18
}
19
20
test_expect_success 'reset' '
@@ -42,6 +41,14 @@ test_expect_success 'fg bg attr' '
41
color "blue red ul" "[4;34;41m"
42
'
43
44
+test_expect_success 'fg bg attr...' '
45
+ color "blue bold dim ul blink reverse" "[1;2;4;5;7;34m"
46
+'
47
+
48
+test_expect_success 'long color specification' '
49
+ color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m"
50
+'
51
+
52
test_expect_success '256 colors' '
53
color "254 bold 255" "[1;38;5;254;48;5;255m"
54
'