Skip to content

Commit 8b12413

Browse files
committed
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 <[email protected]>
1 parent c503467 commit 8b12413

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

color.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void color_parse_mem(const char *value, int value_len, const char *var,
4949
{
5050
const char *ptr = value;
5151
int len = value_len;
52-
int attr = -1;
52+
unsigned int attr = 0;
5353
int fg = -2;
5454
int bg = -2;
5555

@@ -58,7 +58,7 @@ void color_parse_mem(const char *value, int value_len, const char *var,
5858
return;
5959
}
6060

61-
/* [fg [bg]] [attr] */
61+
/* [fg [bg]] [attr]... */
6262
while (len > 0) {
6363
const char *word = ptr;
6464
int val, wordlen = 0;
@@ -87,19 +87,27 @@ void color_parse_mem(const char *value, int value_len, const char *var,
8787
goto bad;
8888
}
8989
val = parse_attr(word, wordlen);
90-
if (val < 0 || attr != -1)
90+
if (0 <= val)
91+
attr |= (1 << val);
92+
else
9193
goto bad;
92-
attr = val;
9394
}
9495

95-
if (attr >= 0 || fg >= 0 || bg >= 0) {
96+
if (attr || fg >= 0 || bg >= 0) {
9697
int sep = 0;
98+
int i;
9799

98100
*dst++ = '\033';
99101
*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;
103111
}
104112
if (fg >= 0) {
105113
if (sep++)

color.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
#ifndef COLOR_H
22
#define COLOR_H
33

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
618

719
/*
820
* This variable stores the value of color.ui

t/t4026-color.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ test_description='Test diff/status color escape codes'
88

99
color()
1010
{
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"
1313
}
1414

1515
invalid_color()
1616
{
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"
1918
}
2019

2120
test_expect_success 'reset' '
@@ -42,6 +41,14 @@ test_expect_success 'fg bg attr' '
4241
color "blue red ul" "[4;34;41m"
4342
'
4443

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+
4552
test_expect_success '256 colors' '
4653
color "254 bold 255" "[1;38;5;254;48;5;255m"
4754
'

0 commit comments

Comments
 (0)