decorate: color each token separately

Wrap "tag:" prefixes and the arrows in "HEAD -> branch" decorations in
their own color sequences. Otherwise, if --graph is used, tag names or
arrows can end up uncolored when %w width formatting breaks a line just
before them. This is because --graph resets the color after doing its
drawing at the start of a line.

Amend test t4207-log-decoration-colors.sh accordingly.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Andy Koppe
2023-08-20 19:50:06 +01:00
committed by Junio C Hamano
parent b87a9a2c1e
commit dcb347f837
2 changed files with 36 additions and 22 deletions

View File

@ -342,26 +342,34 @@ void format_decorations(struct strbuf *sb,
* appeared, skipping the entry for current. * appeared, skipping the entry for current.
*/ */
if (decoration != current_and_HEAD) { if (decoration != current_and_HEAD) {
const char *color =
decorate_get_color(use_color, decoration->type);
if (*prefix) { if (*prefix) {
strbuf_addstr(sb, color_commit); strbuf_addstr(sb, color_commit);
strbuf_addstr(sb, prefix); strbuf_addstr(sb, prefix);
strbuf_addstr(sb, color_reset); strbuf_addstr(sb, color_reset);
} }
strbuf_addstr(sb, decorate_get_color(use_color, decoration->type)); if (decoration->type == DECORATION_REF_TAG) {
if (decoration->type == DECORATION_REF_TAG) strbuf_addstr(sb, color);
strbuf_addstr(sb, "tag: "); strbuf_addstr(sb, "tag: ");
strbuf_addstr(sb, color_reset);
}
strbuf_addstr(sb, color);
show_name(sb, decoration); show_name(sb, decoration);
strbuf_addstr(sb, color_reset);
if (current_and_HEAD && if (current_and_HEAD &&
decoration->type == DECORATION_REF_HEAD) { decoration->type == DECORATION_REF_HEAD) {
strbuf_addstr(sb, color);
strbuf_addstr(sb, " -> "); strbuf_addstr(sb, " -> ");
strbuf_addstr(sb, color_reset); strbuf_addstr(sb, color_reset);
strbuf_addstr(sb, decorate_get_color(use_color, current_and_HEAD->type)); strbuf_addstr(sb, decorate_get_color(use_color, current_and_HEAD->type));
show_name(sb, current_and_HEAD); show_name(sb, current_and_HEAD);
strbuf_addstr(sb, color_reset);
} }
strbuf_addstr(sb, color_reset);
prefix = separator; prefix = separator;
} }

View File

@ -53,15 +53,17 @@ cmp_filtered_decorations () {
# to this test since it does not contain any decoration, hence --first-parent # to this test since it does not contain any decoration, hence --first-parent
test_expect_success 'commit decorations colored correctly' ' test_expect_success 'commit decorations colored correctly' '
cat >expect <<-EOF && cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_reset}${c_branch}main${c_reset}${c_commit}, \ ${c_HEAD} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \ ${c_reset}${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B ${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit}, \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_commit}, \
${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1 ${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset} \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
On main: Changes to A.t ${c_stash}refs/stash${c_reset}${c_commit})${c_reset} On main: Changes to A.t
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
EOF EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual && git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual &&
@ -76,12 +78,14 @@ test_expect_success 'test coloring with replace-objects' '
git replace HEAD~1 HEAD~2 && git replace HEAD~1 HEAD~2 &&
cat >expect <<-EOF && cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_reset}${c_branch}main${c_reset}${c_commit}, \ ${c_HEAD} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D ${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit}, \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
EOF EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual && git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
@ -100,13 +104,15 @@ test_expect_success 'test coloring with grafted commit' '
git replace --graft HEAD HEAD~2 && git replace --graft HEAD HEAD~2 &&
cat >expect <<-EOF && cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_reset}${c_branch}main${c_reset}${c_commit}, \ ${c_HEAD} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: D${c_reset}${c_commit}, \ ${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B ${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A ${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
EOF EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual && git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&