diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-07-11 10:31:05 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-07-11 10:31:05 -0700 |
commit | 3c5de5c77b0718b47010b146160ecff6309f86b5 (patch) | |
tree | 10dfe3c6e701fab8fee60d0059a07b72cfd34c59 | |
parent | bb2d8a817df91c68742e10ace2a791de176f7247 (diff) | |
parent | 9dc3515cf005639317fb95492b3157aadf056923 (diff) | |
download | git-3c5de5c77b0718b47010b146160ecff6309f86b5.tar.gz |
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
-rw-r--r-- | Documentation/config.txt | 49 | ||||
-rw-r--r-- | color.c | 35 | ||||
-rw-r--r-- | color.h | 15 | ||||
-rw-r--r-- | git-compat-util.h | 17 | ||||
-rwxr-xr-x | t/t4026-color.sh | 9 |
5 files changed, 86 insertions, 39 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index e208af118d..db05dec743 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -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). -+ -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 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. + 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. ++ +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. ++ +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 @@ -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; } @@ -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, diff --git a/git-compat-util.h b/git-compat-util.h index 49d4029b8d..c99cddc54b 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -474,6 +474,23 @@ static inline int skip_prefix(const char *str, const char *prefix, } /* + * 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. */ diff --git a/t/t4026-color.sh b/t/t4026-color.sh index 2b32c4fbe6..ec78c5e3ac 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -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' ' |