Skip to content

Commit 18fb7ff

Browse files
peffgitster
authored andcommitted
pretty: respect color settings for %C placeholders
The color placeholders have traditionally been unconditional, showing colors even when git is not otherwise configured to do so. This was not so bad for their original use, which was on the command-line (and the user could decide at that moment whether to add colors or not). But these days we have configured formats via pretty.*, and those should operate correctly in multiple contexts. In 3082517 (log --format: teach %C(auto,black) to respect color config, 2012-12-17), we gave an extended placeholder that could be used to accomplish this. But it's rather clunky to use, because you have to specify it individually for each color (and their matching resets) in the format. We shied away from just switching the default to auto, because it is technically breaking backwards compatibility. However, there's not really a use case for unconditional colors. The most plausible reason you would want them is to redirect "git log" output to a file. But there, the right answer is --color=always, as it does the right thing both with custom user-format colors and git-generated colors. So let's switch to the more useful default. In the off-chance that somebody really does find a use for unconditional colors without wanting to enable the rest of git's colors, we provide a new %C(always,...) to enable the old behavior. And we can remind them of --color=always in the documentation. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d75dfb1 commit 18fb7ff

File tree

3 files changed

+84
-45
lines changed

3 files changed

+84
-45
lines changed

Documentation/pretty-formats.txt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,17 @@ endif::git-rev-list[]
173173
- '%Cblue': switch color to blue
174174
- '%Creset': reset color
175175
- '%C(...)': color specification, as described under Values in the
176-
"CONFIGURATION FILE" section of linkgit:git-config[1];
177-
adding `auto,` at the beginning (e.g. `%C(auto,red)`) will emit
178-
color only when colors are enabled for log output (by `color.diff`,
179-
`color.ui`, or `--color`, and respecting the `auto` settings of the
180-
former if we are going to a terminal). `auto` alone (i.e.
181-
`%C(auto)`) will turn on auto coloring on the next placeholders
182-
until the color is switched again.
176+
"CONFIGURATION FILE" section of linkgit:git-config[1].
177+
By default, colors are shown only when enabled for log output (by
178+
`color.diff`, `color.ui`, or `--color`, and respecting the `auto`
179+
settings of the former if we are going to a terminal). `%C(auto,...)`
180+
is accepted as a historical synonym for the default (e.g.,
181+
`%C(auto,red)`). Specifying `%C(always,...) will show the colors
182+
even when color is not otherwise enabled (though consider
183+
just using `--color=always` to enable color for the whole output,
184+
including this format and anything else git might color). `auto`
185+
alone (i.e. `%C(auto)`) will turn on auto coloring on the next
186+
placeholders until the color is switched again.
183187
- '%m': left (`<`), right (`>`) or boundary (`-`) mark
184188
- '%n': newline
185189
- '%%': a raw '%'

pretty.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
947947
struct format_commit_context *c)
948948
{
949949
const char *rest = placeholder;
950+
const char *basic_color = NULL;
950951

951952
if (placeholder[1] == '(') {
952953
const char *begin = placeholder + 2;
@@ -955,23 +956,41 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
955956

956957
if (!end)
957958
return 0;
959+
958960
if (skip_prefix(begin, "auto,", &begin)) {
959961
if (!want_color(c->pretty_ctx->color))
960962
return end - placeholder + 1;
963+
} else if (skip_prefix(begin, "always,", &begin)) {
964+
/* nothing to do; we do not respect want_color at all */
965+
} else {
966+
/* the default is the same as "auto" */
967+
if (!want_color(c->pretty_ctx->color))
968+
return end - placeholder + 1;
961969
}
970+
962971
if (color_parse_mem(begin, end - begin, color) < 0)
963972
die(_("unable to parse --pretty format"));
964973
strbuf_addstr(sb, color);
965974
return end - placeholder + 1;
966975
}
976+
977+
/*
978+
* We handle things like "%C(red)" above; for historical reasons, there
979+
* are a few colors that can be specified without parentheses (and
980+
* they cannot support things like "auto" or "always" at all).
981+
*/
967982
if (skip_prefix(placeholder + 1, "red", &rest))
968-
strbuf_addstr(sb, GIT_COLOR_RED);
983+
basic_color = GIT_COLOR_RED;
969984
else if (skip_prefix(placeholder + 1, "green", &rest))
970-
strbuf_addstr(sb, GIT_COLOR_GREEN);
985+
basic_color = GIT_COLOR_GREEN;
971986
else if (skip_prefix(placeholder + 1, "blue", &rest))
972-
strbuf_addstr(sb, GIT_COLOR_BLUE);
987+
basic_color = GIT_COLOR_BLUE;
973988
else if (skip_prefix(placeholder + 1, "reset", &rest))
974-
strbuf_addstr(sb, GIT_COLOR_RESET);
989+
basic_color = GIT_COLOR_RESET;
990+
991+
if (basic_color && want_color(c->pretty_ctx->color))
992+
strbuf_addstr(sb, basic_color);
993+
975994
return rest - placeholder;
976995
}
977996

t/t6006-rev-list-format.sh

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ test_format () {
5959
}
6060

6161
# Feed to --format to provide predictable colored sequences.
62+
BASIC_COLOR='%Credfoo%Creset'
63+
COLOR='%C(red)foo%C(reset)'
6264
AUTO_COLOR='%C(auto,red)foo%C(auto,reset)'
65+
ALWAYS_COLOR='%C(always,red)foo%C(always,reset)'
6366
has_color () {
6467
test_decode_color <"$1" >decoded &&
6568
echo "<RED>foo<RESET>" >expect &&
@@ -177,7 +180,7 @@ test_expect_success 'basic colors' '
177180
<RED>foo<GREEN>bar<BLUE>baz<RESET>xyzzy
178181
EOF
179182
format="%Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy" &&
180-
git rev-list --format="$format" -1 master >actual.raw &&
183+
git rev-list --color --format="$format" -1 master >actual.raw &&
181184
test_decode_color <actual.raw >actual &&
182185
test_cmp expect actual
183186
'
@@ -188,48 +191,61 @@ test_expect_success 'advanced colors' '
188191
<BOLD;RED;BYELLOW>foo<RESET>
189192
EOF
190193
format="%C(red yellow bold)foo%C(reset)" &&
191-
git rev-list --format="$format" -1 master >actual.raw &&
194+
git rev-list --color --format="$format" -1 master >actual.raw &&
192195
test_decode_color <actual.raw >actual &&
193196
test_cmp expect actual
194197
'
195198

196-
test_expect_success '%C(auto,...) does not enable color by default' '
197-
git log --format=$AUTO_COLOR -1 >actual &&
198-
has_no_color actual
199-
'
200-
201-
test_expect_success '%C(auto,...) enables colors for color.diff' '
202-
git -c color.diff=always log --format=$AUTO_COLOR -1 >actual &&
203-
has_color actual
204-
'
205-
206-
test_expect_success '%C(auto,...) enables colors for color.ui' '
207-
git -c color.ui=always log --format=$AUTO_COLOR -1 >actual &&
208-
has_color actual
209-
'
199+
for spec in \
200+
"%Cred:$BASIC_COLOR" \
201+
"%C(...):$COLOR" \
202+
"%C(auto,...):$AUTO_COLOR"
203+
do
204+
desc=${spec%%:*}
205+
color=${spec#*:}
206+
test_expect_success "$desc does not enable color by default" '
207+
git log --format=$color -1 >actual &&
208+
has_no_color actual
209+
'
210210

211-
test_expect_success '%C(auto,...) respects --color' '
212-
git log --format=$AUTO_COLOR -1 --color >actual &&
213-
has_color actual
214-
'
211+
test_expect_success "$desc enables colors for color.diff" '
212+
git -c color.diff=always log --format=$color -1 >actual &&
213+
has_color actual
214+
'
215215

216-
test_expect_success '%C(auto,...) respects --no-color' '
217-
git -c color.ui=always log --format=$AUTO_COLOR -1 --no-color >actual &&
218-
has_no_color actual
219-
'
216+
test_expect_success "$desc enables colors for color.ui" '
217+
git -c color.ui=always log --format=$color -1 >actual &&
218+
has_color actual
219+
'
220220

221-
test_expect_success TTY '%C(auto,...) respects --color=auto (stdout is tty)' '
222-
test_terminal env TERM=vt100 \
223-
git log --format=$AUTO_COLOR -1 --color=auto >actual &&
224-
has_color actual
225-
'
221+
test_expect_success "$desc respects --color" '
222+
git log --format=$color -1 --color >actual &&
223+
has_color actual
224+
'
226225

227-
test_expect_success '%C(auto,...) respects --color=auto (stdout not tty)' '
228-
(
229-
TERM=vt100 && export TERM &&
230-
git log --format=$AUTO_COLOR -1 --color=auto >actual &&
226+
test_expect_success "$desc respects --no-color" '
227+
git -c color.ui=always log --format=$color -1 --no-color >actual &&
231228
has_no_color actual
232-
)
229+
'
230+
231+
test_expect_success TTY "$desc respects --color=auto (stdout is tty)" '
232+
test_terminal env TERM=vt100 \
233+
git log --format=$color -1 --color=auto >actual &&
234+
has_color actual
235+
'
236+
237+
test_expect_success "$desc respects --color=auto (stdout not tty)" '
238+
(
239+
TERM=vt100 && export TERM &&
240+
git log --format=$color -1 --color=auto >actual &&
241+
has_no_color actual
242+
)
243+
'
244+
done
245+
246+
test_expect_success '%C(always,...) enables color even without tty' '
247+
git log --format=$ALWAYS_COLOR -1 >actual &&
248+
has_color actual
233249
'
234250

235251
test_expect_success '%C(auto) respects --color' '

0 commit comments

Comments
 (0)