Merge branch 'jk/ansi-color'
The output coloring scheme learned two new attributes, italic and strike, in addition to existing bold, reverse, etc. * jk/ansi-color: color: support strike-through attribute color: support "italic" attribute color: allow "no-" for negating attributes color: refactor parse_attr add skip_prefix_mem helper doc: refactor description of color format color: fix max-size comment
This commit is contained in:
commit
3c5de5c77b
@ -150,27 +150,34 @@ integer::
|
||||
1024", "by 1024x1024", etc.
|
||||
|
||||
color::
|
||||
The value for a variables that takes a color is a list of
|
||||
colors (at most two) and attributes (at most one), separated
|
||||
by spaces. The colors accepted are `normal`, `black`,
|
||||
`red`, `green`, `yellow`, `blue`, `magenta`, `cyan` and
|
||||
`white`; the attributes are `bold`, `dim`, `ul`, `blink` and
|
||||
`reverse`. The first color given is the foreground; the
|
||||
second is the background. The position of the attribute, if
|
||||
any, doesn't matter. Attributes may be turned off specifically
|
||||
by prefixing them with `no` (e.g., `noreverse`, `noul`, etc).
|
||||
The value for a variable that takes a color is a list of
|
||||
colors (at most two, one for foreground and one for background)
|
||||
and attributes (as many as you want), separated by spaces.
|
||||
+
|
||||
Colors (foreground and background) may also be given as numbers between
|
||||
0 and 255; these use ANSI 256-color mode (but note that not all
|
||||
terminals may support this). If your terminal supports it, you may also
|
||||
specify 24-bit RGB values as hex, like `#ff0ab3`.
|
||||
The basic colors accepted are `normal`, `black`, `red`, `green`, `yellow`,
|
||||
`blue`, `magenta`, `cyan` and `white`. The first color given is the
|
||||
foreground; the second is the background.
|
||||
+
|
||||
The attributes are meant to be reset at the beginning of each item
|
||||
in the colored output, so setting color.decorate.branch to `black`
|
||||
will paint that branch name in a plain `black`, even if the previous
|
||||
thing on the same output line (e.g. opening parenthesis before the
|
||||
list of branch names in `log --decorate` output) is set to be
|
||||
painted with `bold` or some other attribute.
|
||||
Colors may also be given as numbers between 0 and 255; these use ANSI
|
||||
256-color mode (but note that not all terminals may support this). If
|
||||
your terminal supports it, you may also specify 24-bit RGB values as
|
||||
hex, like `#ff0ab3`.
|
||||
+
|
||||
The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`,
|
||||
`italic`, and `strike` (for crossed-out or "strikethrough" letters).
|
||||
The position of any attributes with respect to the colors
|
||||
(before, after, or in between), doesn't matter. Specific attributes may
|
||||
be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
|
||||
`no-ul`, etc).
|
||||
+
|
||||
For git's pre-defined color slots, the attributes are meant to be reset
|
||||
at the beginning of each item in the colored output. So setting
|
||||
`color.decorate.branch` to `black` will paint that branch name in a
|
||||
plain `black`, even if the previous thing on the same output line (e.g.
|
||||
opening parenthesis before the list of branch names in `log --decorate`
|
||||
output) is set to be painted with `bold` or some other attribute.
|
||||
However, custom log formats may do more complicated and layered
|
||||
coloring, and the negated forms may be useful there.
|
||||
|
||||
pathname::
|
||||
A variable that takes a pathname value can be given a
|
||||
|
35
color.c
35
color.c
@ -123,19 +123,34 @@ static int parse_color(struct color *out, const char *name, int len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int parse_attr(const char *name, int len)
|
||||
static int parse_attr(const char *name, size_t len)
|
||||
{
|
||||
static const int attr_values[] = { 1, 2, 4, 5, 7,
|
||||
22, 22, 24, 25, 27 };
|
||||
static const char * const attr_names[] = {
|
||||
"bold", "dim", "ul", "blink", "reverse",
|
||||
"nobold", "nodim", "noul", "noblink", "noreverse"
|
||||
static const struct {
|
||||
const char *name;
|
||||
size_t len;
|
||||
int val, neg;
|
||||
} attrs[] = {
|
||||
#define ATTR(x, val, neg) { (x), sizeof(x)-1, (val), (neg) }
|
||||
ATTR("bold", 1, 22),
|
||||
ATTR("dim", 2, 22),
|
||||
ATTR("italic", 3, 23),
|
||||
ATTR("ul", 4, 24),
|
||||
ATTR("blink", 5, 25),
|
||||
ATTR("reverse", 7, 27),
|
||||
ATTR("strike", 9, 29)
|
||||
#undef ATTR
|
||||
};
|
||||
int negate = 0;
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
|
||||
const char *str = attr_names[i];
|
||||
if (!strncasecmp(name, str, len) && !str[len])
|
||||
return attr_values[i];
|
||||
|
||||
if (skip_prefix_mem(name, len, "no", &name, &len)) {
|
||||
skip_prefix_mem(name, len, "-", &name, &len);
|
||||
negate = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(attrs); i++) {
|
||||
if (attrs[i].len == len && !memcmp(attrs[i].name, name, len))
|
||||
return negate ? attrs[i].neg : attrs[i].val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
15
color.h
15
color.h
@ -3,20 +3,23 @@
|
||||
|
||||
struct strbuf;
|
||||
|
||||
/* 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 + ';' 3 * 10 (e.g. "1;")
|
||||
* - attr + ';' 2 * num_attr (e.g. "1;")
|
||||
* - no-attr + ';' 3 * num_attr (e.g. "22;")
|
||||
* - fg color + ';' 17 (e.g. "38;2;255;255;255;")
|
||||
* - bg color + ';' 17 (e.g. "48;2;255;255;255;")
|
||||
* - terminating 'm' NUL 2
|
||||
*
|
||||
* The above overcounts attr (we only use 5 not 8) and one semicolon
|
||||
* but it is close enough.
|
||||
* The above overcounts by one semicolon but it is close enough.
|
||||
*
|
||||
* The space for attributes is also slightly overallocated, as
|
||||
* the negation for some attributes is the same (e.g., nobold and nodim).
|
||||
*
|
||||
* We allocate space for 7 attributes.
|
||||
*/
|
||||
#define COLOR_MAXLEN 70
|
||||
#define COLOR_MAXLEN 75
|
||||
|
||||
/*
|
||||
* IMPORTANT: Due to the way these color codes are emulated on Windows,
|
||||
|
@ -473,6 +473,23 @@ static inline int skip_prefix(const char *str, const char *prefix,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Like skip_prefix, but promises never to read past "len" bytes of the input
|
||||
* buffer, and returns the remaining number of bytes in "out" via "outlen".
|
||||
*/
|
||||
static inline int skip_prefix_mem(const char *buf, size_t len,
|
||||
const char *prefix,
|
||||
const char **out, size_t *outlen)
|
||||
{
|
||||
size_t prefix_len = strlen(prefix);
|
||||
if (prefix_len <= len && !memcmp(buf, prefix, prefix_len)) {
|
||||
*out = buf + prefix_len;
|
||||
*outlen = len - prefix_len;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If buf ends with suffix, return 1 and subtract the length of the suffix
|
||||
* from *len. Otherwise, return 0 and leave *len untouched.
|
||||
|
@ -50,14 +50,19 @@ test_expect_success 'attr negation' '
|
||||
color "nobold nodim noul noblink noreverse" "[22;24;25;27m"
|
||||
'
|
||||
|
||||
test_expect_success '"no-" variant of negation' '
|
||||
color "no-bold no-blink" "[22;25m"
|
||||
'
|
||||
|
||||
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 'absurdly long color specification' '
|
||||
color \
|
||||
"#ffffff #ffffff bold nobold dim nodim ul noul blink noblink reverse noreverse" \
|
||||
"[1;2;4;5;7;22;24;25;27;38;2;255;255;255;48;2;255;255;255m"
|
||||
"#ffffff #ffffff bold nobold dim nodim italic noitalic
|
||||
ul noul blink noblink reverse noreverse strike nostrike" \
|
||||
"[1;2;3;4;5;7;9;22;23;24;25;27;29;38;2;255;255;255;48;2;255;255;255m"
|
||||
'
|
||||
|
||||
test_expect_success '0-7 are aliases for basic ANSI color names' '
|
||||
|
Loading…
Reference in New Issue
Block a user