diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 4d6dac5770..973d19606b 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -173,13 +173,17 @@ endif::git-rev-list[] - '%Cblue': switch color to blue - '%Creset': reset color - '%C(...)': color specification, as described under Values in the - "CONFIGURATION FILE" section of linkgit:git-config[1]; - adding `auto,` at the beginning (e.g. `%C(auto,red)`) will emit - color only when colors are enabled for log output (by `color.diff`, - `color.ui`, or `--color`, and respecting the `auto` settings of the - former if we are going to a terminal). `auto` alone (i.e. - `%C(auto)`) will turn on auto coloring on the next placeholders - until the color is switched again. + "CONFIGURATION FILE" section of linkgit:git-config[1]. + By default, colors are shown only when enabled for log output (by + `color.diff`, `color.ui`, or `--color`, and respecting the `auto` + settings of the former if we are going to a terminal). `%C(auto,...)` + is accepted as a historical synonym for the default (e.g., + `%C(auto,red)`). Specifying `%C(always,...) will show the colors + even when color is not otherwise enabled (though consider + just using `--color=always` to enable color for the whole output, + including this format and anything else git might color). `auto` + alone (i.e. `%C(auto)`) will turn on auto coloring on the next + placeholders until the color is switched again. - '%m': left (`<`), right (`>`) or boundary (`-`) mark - '%n': newline - '%%': a raw '%' diff --git a/pretty.c b/pretty.c index e4b561c582..39cad5112b 100644 --- a/pretty.c +++ b/pretty.c @@ -947,6 +947,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */ struct format_commit_context *c) { const char *rest = placeholder; + const char *basic_color = NULL; if (placeholder[1] == '(') { const char *begin = placeholder + 2; @@ -955,23 +956,41 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */ if (!end) return 0; + if (skip_prefix(begin, "auto,", &begin)) { if (!want_color(c->pretty_ctx->color)) return end - placeholder + 1; + } else if (skip_prefix(begin, "always,", &begin)) { + /* nothing to do; we do not respect want_color at all */ + } else { + /* the default is the same as "auto" */ + if (!want_color(c->pretty_ctx->color)) + return end - placeholder + 1; } + if (color_parse_mem(begin, end - begin, color) < 0) die(_("unable to parse --pretty format")); strbuf_addstr(sb, color); return end - placeholder + 1; } + + /* + * We handle things like "%C(red)" above; for historical reasons, there + * are a few colors that can be specified without parentheses (and + * they cannot support things like "auto" or "always" at all). + */ if (skip_prefix(placeholder + 1, "red", &rest)) - strbuf_addstr(sb, GIT_COLOR_RED); + basic_color = GIT_COLOR_RED; else if (skip_prefix(placeholder + 1, "green", &rest)) - strbuf_addstr(sb, GIT_COLOR_GREEN); + basic_color = GIT_COLOR_GREEN; else if (skip_prefix(placeholder + 1, "blue", &rest)) - strbuf_addstr(sb, GIT_COLOR_BLUE); + basic_color = GIT_COLOR_BLUE; else if (skip_prefix(placeholder + 1, "reset", &rest)) - strbuf_addstr(sb, GIT_COLOR_RESET); + basic_color = GIT_COLOR_RESET; + + if (basic_color && want_color(c->pretty_ctx->color)) + strbuf_addstr(sb, basic_color); + return rest - placeholder; } diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index 7b97a90bae..b326d550f3 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -59,7 +59,10 @@ test_format () { } # Feed to --format to provide predictable colored sequences. +BASIC_COLOR='%Credfoo%Creset' +COLOR='%C(red)foo%C(reset)' AUTO_COLOR='%C(auto,red)foo%C(auto,reset)' +ALWAYS_COLOR='%C(always,red)foo%C(always,reset)' has_color () { test_decode_color <"$1" >decoded && echo "foo" >expect && @@ -177,7 +180,7 @@ test_expect_success 'basic colors' ' foobarbazxyzzy EOF format="%Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy" && - git rev-list --format="$format" -1 master >actual.raw && + git rev-list --color --format="$format" -1 master >actual.raw && test_decode_color actual && test_cmp expect actual ' @@ -188,48 +191,61 @@ test_expect_success 'advanced colors' ' foo EOF format="%C(red yellow bold)foo%C(reset)" && - git rev-list --format="$format" -1 master >actual.raw && + git rev-list --color --format="$format" -1 master >actual.raw && test_decode_color actual && test_cmp expect actual ' -test_expect_success '%C(auto,...) does not enable color by default' ' - git log --format=$AUTO_COLOR -1 >actual && - has_no_color actual -' - -test_expect_success '%C(auto,...) enables colors for color.diff' ' - git -c color.diff=always log --format=$AUTO_COLOR -1 >actual && - has_color actual -' - -test_expect_success '%C(auto,...) enables colors for color.ui' ' - git -c color.ui=always log --format=$AUTO_COLOR -1 >actual && - has_color actual -' - -test_expect_success '%C(auto,...) respects --color' ' - git log --format=$AUTO_COLOR -1 --color >actual && - has_color actual -' - -test_expect_success '%C(auto,...) respects --no-color' ' - git -c color.ui=always log --format=$AUTO_COLOR -1 --no-color >actual && - has_no_color actual -' - -test_expect_success TTY '%C(auto,...) respects --color=auto (stdout is tty)' ' - test_terminal env TERM=vt100 \ - git log --format=$AUTO_COLOR -1 --color=auto >actual && - has_color actual -' - -test_expect_success '%C(auto,...) respects --color=auto (stdout not tty)' ' - ( - TERM=vt100 && export TERM && - git log --format=$AUTO_COLOR -1 --color=auto >actual && +for spec in \ + "%Cred:$BASIC_COLOR" \ + "%C(...):$COLOR" \ + "%C(auto,...):$AUTO_COLOR" +do + desc=${spec%%:*} + color=${spec#*:} + test_expect_success "$desc does not enable color by default" ' + git log --format=$color -1 >actual && has_no_color actual - ) + ' + + test_expect_success "$desc enables colors for color.diff" ' + git -c color.diff=always log --format=$color -1 >actual && + has_color actual + ' + + test_expect_success "$desc enables colors for color.ui" ' + git -c color.ui=always log --format=$color -1 >actual && + has_color actual + ' + + test_expect_success "$desc respects --color" ' + git log --format=$color -1 --color >actual && + has_color actual + ' + + test_expect_success "$desc respects --no-color" ' + git -c color.ui=always log --format=$color -1 --no-color >actual && + has_no_color actual + ' + + test_expect_success TTY "$desc respects --color=auto (stdout is tty)" ' + test_terminal env TERM=vt100 \ + git log --format=$color -1 --color=auto >actual && + has_color actual + ' + + test_expect_success "$desc respects --color=auto (stdout not tty)" ' + ( + TERM=vt100 && export TERM && + git log --format=$color -1 --color=auto >actual && + has_no_color actual + ) + ' +done + +test_expect_success '%C(always,...) enables color even without tty' ' + git log --format=$ALWAYS_COLOR -1 >actual && + has_color actual ' test_expect_success '%C(auto) respects --color' '