builtin/blame: dim uninteresting metadata lines

When using git-blame lots of lines contain redundant information, for
example in hunks that consist of multiple lines, the metadata (commit
name, author, date) are repeated. A reader may not be interested in those,
so offer an option to color the information that is repeated from the
previous line differently. Traditionally, we use CYAN for lines that
are less interesting than others (e.g. hunk header), so go with that.

The command line option '--color-lines' will trigger the coloring of
repeated lines, and the config option 'color.blame.colorLines' is
provided to select the color. Setting the config option doesn't imply
that repeated lines are colored. A later patch will introduce a config
to enable this mode by default.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Stefan Beller 2018-04-23 17:08:58 -07:00 committed by Junio C Hamano
parent 75e5e9c3f7
commit cdc2d5f11f
3 changed files with 59 additions and 4 deletions

View File

@ -1218,6 +1218,11 @@ color.status.<slot>::
status short-format), or
`unmerged` (files which have unmerged changes).
color.blame.repeatedLines::
Use the customized color for the part of git-blame output that
is repeated meta information per line (such as commit id,
author name, date and timezone). Defaults to cyan.
color.ui::
This variable determines the default value for variables such
as `color.diff` and `color.grep` that control the use of color

View File

@ -7,6 +7,7 @@
#include "cache.h"
#include "config.h"
#include "color.h"
#include "builtin.h"
#include "commit.h"
#include "diff.h"
@ -46,6 +47,7 @@ static int xdl_opts;
static int abbrev = -1;
static int no_whole_file_rename;
static int show_progress;
static char repeated_meta_color[COLOR_MAXLEN];
static struct date_mode blame_date_mode = { DATE_ISO8601 };
static size_t blame_date_width;
@ -316,10 +318,11 @@ static const char *format_time(timestamp_t time, const char *tz_str,
#define OUTPUT_PORCELAIN 010
#define OUTPUT_SHOW_NAME 020
#define OUTPUT_SHOW_NUMBER 040
#define OUTPUT_SHOW_SCORE 0100
#define OUTPUT_NO_AUTHOR 0200
#define OUTPUT_SHOW_SCORE 0100
#define OUTPUT_NO_AUTHOR 0200
#define OUTPUT_SHOW_EMAIL 0400
#define OUTPUT_LINE_PORCELAIN 01000
#define OUTPUT_LINE_PORCELAIN 01000
#define OUTPUT_COLOR_LINE 02000
static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
{
@ -375,6 +378,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
struct commit_info ci;
char hex[GIT_MAX_HEXSZ + 1];
int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
const char *color = NULL, *reset = NULL;
get_commit_info(suspect->commit, &ci, 1);
oid_to_hex_r(hex, &suspect->commit->object.oid);
@ -384,6 +388,18 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
char ch;
int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev;
if (opt & OUTPUT_COLOR_LINE) {
if (cnt > 0) {
color = repeated_meta_color;
reset = GIT_COLOR_RESET;
} else {
color = NULL;
reset = NULL;
}
}
if (color)
fputs(color, stdout);
if (suspect->commit->object.flags & UNINTERESTING) {
if (blank_boundary)
memset(hex, ' ', length);
@ -433,6 +449,8 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
printf(" %*d) ",
max_digits, ent->lno + 1 + cnt);
}
if (reset)
fputs(reset, stdout);
do {
ch = *cp++;
putchar(ch);
@ -607,6 +625,12 @@ static int git_blame_config(const char *var, const char *value, void *cb)
parse_date_format(value, &blame_date_mode);
return 0;
}
if (!strcmp(var, "color.blame.repeatedlines")) {
if (color_parse_mem(value, strlen(value), repeated_meta_color))
warning(_("invalid color '%s' in color.blame.repeatedLines"),
value);
return 0;
}
if (git_diff_heuristic_config(var, value, cb) < 0)
return -1;
@ -681,6 +705,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
OPT_BIT('s', NULL, &output_option, N_("Suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
OPT_BIT('e', "show-email", &output_option, N_("Show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
OPT_BIT('w', NULL, &xdl_opts, N_("Ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE),
/*
* The following two options are parsed by parse_revision_opt()
@ -940,8 +965,14 @@ parse_done:
blame_coalesce(&sb);
if (!(output_option & OUTPUT_PORCELAIN))
if (!(output_option & OUTPUT_PORCELAIN)) {
find_alignment(&sb, &output_option);
if (!*repeated_meta_color &&
(output_option & OUTPUT_COLOR_LINE))
strcpy(repeated_meta_color, GIT_COLOR_CYAN);
}
if (output_option & OUTPUT_ANNOTATE_COMPAT)
output_option &= ~OUTPUT_COLOR_LINE;
output(&sb, output_option);
free((void *)sb.final_buf);

19
t/t8012-blame-colors.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
test_description='colored git blame'
. ./test-lib.sh
PROG='git blame -c'
. "$TEST_DIRECTORY"/annotate-tests.sh
test_expect_success 'colored blame colors contiguous lines' '
git -c color.blame.repeatedLines=yellow blame --color-lines --abbrev=12 hello.c >actual.raw &&
test_decode_color <actual.raw >actual &&
grep "<YELLOW>" <actual >darkened &&
grep "(F" darkened > F.expect &&
grep "(H" darkened > H.expect &&
test_line_count = 2 F.expect &&
test_line_count = 3 H.expect
'
test_done