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>
This commit is contained in:
Junio C Hamano 2010-02-27 18:56:38 -08:00
parent c5034673fd
commit 8b124135a9
3 changed files with 41 additions and 14 deletions

24
color.c
View File

@ -49,7 +49,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;
@ -58,7 +58,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;
@ -87,19 +87,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++)

16
color.h
View File

@ -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
/*
* This variable stores the value of color.ui

View File

@ -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"
'