From: Stefan Beller <sbeller@google.com>
To: git@vger.kernel.org
Cc: Stefan Beller <sbeller@google.com>
Subject: [PATCH 3/4] builtin/blame: add option to color metadata fields separately
Date: Thu, 9 Nov 2017 17:10:01 -0800 [thread overview]
Message-ID: <20171110011002.10179-4-sbeller@google.com> (raw)
In-Reply-To: <20171110011002.10179-1-sbeller@google.com>
Unlike the previous commit, this dims colors for each
metadata field individually.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
builtin/blame.c | 82 +++++++++++++++++++++++++++++++++++++++++++------
t/t8012-blame-colors.sh | 38 +++++++++++++++++++++++
2 files changed, 111 insertions(+), 9 deletions(-)
diff --git a/builtin/blame.c b/builtin/blame.c
index d15e901357..9d460597a2 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -323,6 +323,7 @@ static const char *format_time(timestamp_t time, const char *tz_str,
#define OUTPUT_SHOW_EMAIL 0400
#define OUTPUT_LINE_PORCELAIN 01000
#define OUTPUT_COLOR_LINE 02000
+#define OUTPUT_COLOR_FIELDS 04000
static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
{
@@ -370,6 +371,33 @@ static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,
putchar('\n');
}
+static int had_same_field_previously(int opt, int field,
+ struct blame_entry *ent,
+ struct blame_entry *prev)
+{
+ struct commit_info ci, prev_ci;
+
+ switch (field) {
+ case OUTPUT_SHOW_SCORE:
+ return ent->score == prev->score;
+ case OUTPUT_SHOW_NAME:
+ return prev->suspect &&
+ !strcmp(ent->suspect->path, prev->suspect->path);
+ case OUTPUT_SHOW_NUMBER:
+ return ent->s_lno == prev->s_lno + prev->num_lines - 1;
+
+ case OUTPUT_NO_AUTHOR:
+ get_commit_info(ent->suspect->commit, &ci, 1);
+ get_commit_info(prev->suspect->commit, &prev_ci, 1);
+ return ((opt & OUTPUT_SHOW_EMAIL) &&
+ !strcmp(ci.author_mail.buf, prev_ci.author_mail.buf)) ||
+ !strcmp(ci.author.buf, prev_ci.author.buf);
+ default:
+ BUG("unknown field");
+ }
+ return 0;
+}
+
static inline void colors_unset(const char **use_color, const char **reset_color)
{
*use_color = "";
@@ -382,17 +410,36 @@ static inline void colors_set(const char **use_color, const char **reset_color)
*reset_color = GIT_COLOR_RESET;
}
+static void setup_field_color(int opt, int cnt, int field,
+ struct blame_entry *ent,
+ struct blame_entry *prev,
+ const char **use_color,
+ const char **reset_color)
+{
+ if (!(opt & OUTPUT_COLOR_FIELDS))
+ return;
+
+ if ((cnt > 0 ||
+ (prev && had_same_field_previously(opt, field, ent, prev))))
+ colors_set(use_color, reset_color);
+ else
+ colors_unset(use_color, reset_color);
+}
+
static void setup_line_color(int opt, int cnt,
const char **use_color,
const char **reset_color)
{
colors_unset(use_color, reset_color);
- if ((opt & OUTPUT_COLOR_LINE) && cnt > 0)
+ if ((opt & (OUTPUT_COLOR_LINE | OUTPUT_COLOR_FIELDS)) && cnt > 0)
colors_set(use_color, reset_color);
}
-static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int opt)
+static void emit_other(struct blame_scoreboard *sb,
+ struct blame_entry *ent,
+ struct blame_entry *prev,
+ int opt)
{
int cnt;
const char *cp;
@@ -432,18 +479,27 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
show_raw_time),
ent->lno + 1 + cnt);
} else {
- if (opt & OUTPUT_SHOW_SCORE)
+ if (opt & OUTPUT_SHOW_SCORE) {
+ setup_field_color(opt, cnt, OUTPUT_SHOW_SCORE,
+ ent, prev, &col, &rcol);
printf(" %s%*d %02d%s", col,
max_score_digits, ent->score,
ent->suspect->refcnt, rcol);
- if (opt & OUTPUT_SHOW_NAME)
+ }
+ if (opt & OUTPUT_SHOW_NAME) {
+ setup_field_color(opt, cnt, OUTPUT_SHOW_NAME,
+ ent, prev, &col, &rcol);
printf(" %s%-*.*s%s", col, longest_file,
longest_file,
suspect->path,
rcol);
- if (opt & OUTPUT_SHOW_NUMBER)
+ }
+ if (opt & OUTPUT_SHOW_NUMBER) {
+ setup_field_color(opt, cnt, OUTPUT_SHOW_NUMBER,
+ ent, prev, &col, &rcol);
printf(" %s%*d%s", col, max_orig_digits,
ent->s_lno + 1 + cnt, rcol);
+ }
if (!(opt & OUTPUT_NO_AUTHOR)) {
const char *name;
int pad;
@@ -452,6 +508,8 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
else
name = ci.author.buf;
pad = longest_author - utf8_strwidth(name);
+ setup_field_color(opt, cnt, OUTPUT_NO_AUTHOR,
+ ent, prev, &col, &rcol);
printf(" %s(%s%*s %10s%s", col,
name, pad, "",
format_time(ci.author_time,
@@ -477,7 +535,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
static void output(struct blame_scoreboard *sb, int option)
{
- struct blame_entry *ent;
+ struct blame_entry *ent, *prev = NULL;
if (option & OUTPUT_PORCELAIN) {
for (ent = sb->ent; ent; ent = ent->next) {
@@ -499,7 +557,8 @@ static void output(struct blame_scoreboard *sb, int option)
if (option & OUTPUT_PORCELAIN)
emit_porcelain(sb, ent, option);
else {
- emit_other(sb, ent, option);
+ emit_other(sb, ent, prev, option);
+ prev = ent;
}
}
}
@@ -717,6 +776,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
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"), OUTPUT_COLOR_LINE),
+ OPT_BIT(0, "color-fields", &output_option, N_("color redundant metadata fields from previous line"), OUTPUT_COLOR_FIELDS),
/*
* The following two options are parsed by parse_revision_opt()
@@ -775,6 +835,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES);
argc = parse_options_end(&ctx);
+ if ((output_option & OUTPUT_COLOR_LINE) &&
+ (output_option & OUTPUT_COLOR_FIELDS))
+ die(_("cannot ask for colored lines and fields at the same time"));
+
if (incremental || (output_option & OUTPUT_PORCELAIN)) {
if (show_progress > 0)
die(_("--progress can't be used with --incremental or porcelain formats"));
@@ -978,8 +1042,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (!(output_option & OUTPUT_PORCELAIN)) {
find_alignment(&sb, &output_option);
- if ((output_option & OUTPUT_COLOR_LINE) &&
- !repeated_meta_color)
+ if (!repeated_meta_color &&
+ (output_option & (OUTPUT_COLOR_LINE | OUTPUT_COLOR_FIELDS)))
repeated_meta_color = GIT_COLOR_DARK;
}
diff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh
index b2de03b777..be491bde9a 100755
--- a/t/t8012-blame-colors.sh
+++ b/t/t8012-blame-colors.sh
@@ -15,4 +15,42 @@ test_expect_success 'colored blame colors continuous lines' '
test_line_count = 3 H.expect
'
+test_expect_success 'colored blame colors continuous fields' '
+
+ git mv hello.c world.c &&
+ git commit -a -m "moved file" &&
+ cat <<-EOF >> world.c &&
+ void world()
+ {
+ puts("world");
+ }
+ EOF
+ git add world.c &&
+ GIT_AUTHOR_NAME="F" GIT_AUTHOR_EMAIL="F@test.git" \
+ git commit -m "forgot to add changes to moved file" &&
+
+ git blame --abbrev=12 --color-fields world.c >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+
+ grep "<BOLD;BLACK>hello.c" actual > colored_hello.expect &&
+ grep "hello.c" actual > all_hello.expect &&
+ test_line_count = 9 colored_hello.expect &&
+ test_line_count = 10 all_hello.expect &&
+
+ grep "<BOLD;BLACK>world.c" actual > colored_world.expect &&
+ grep "world.c" actual > all_world.expect &&
+ test_line_count = 3 colored_world.expect &&
+ test_line_count = 4 all_world.expect &&
+
+ grep "(F" actual > all_F.expect &&
+ grep "<BOLD;BLACK>(F" actual > colored_F.expect &&
+ test_line_count = 8 all_F.expect &&
+ test_line_count = 5 colored_F.expect &&
+
+ grep "(H" actual > all_H.expect &&
+ grep "<BOLD;BLACK>(H" actual > colored_H.expect &&
+ test_line_count = 5 all_H.expect &&
+ test_line_count = 3 colored_H.expect
+'
+
test_done
--
2.15.0.128.gcadd42da22
next prev parent reply other threads:[~2017-11-10 1:10 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-10 1:09 [RFC PATCH 0/4] blame: (dim rep. metadata lines or fields, decay date coloring) Stefan Beller
2017-11-10 1:09 ` [PATCH 1/4] color.h: modernize header Stefan Beller
2017-11-10 1:10 ` [PATCH 2/4] builtin/blame: dim uninteresting metadata Stefan Beller
2017-11-10 1:10 ` Stefan Beller [this message]
2017-11-10 1:10 ` [PATCH 4/4] builtin/blame: highlight recently changed lines Stefan Beller
2018-01-04 22:40 ` [PATCHv3 0/4] blame: (dim rep. metadata lines or fields, decay date coloring) Stefan Beller
2018-01-04 22:40 ` [PATCHv3 1/4] color.h: document and modernize header Stefan Beller
2018-01-08 19:14 ` Junio C Hamano
2018-01-04 22:40 ` [PATCHv3 2/4] builtin/blame: dim uninteresting metadata Stefan Beller
2018-01-08 19:34 ` Junio C Hamano
2018-02-08 21:19 ` Stefan Beller
2018-01-04 22:40 ` [PATCHv3 3/4] builtin/blame: add option to color metadata fields separately Stefan Beller
2018-01-04 22:40 ` [PATCHv3 4/4] builtin/blame: highlight recently changed lines Stefan Beller
2018-01-08 19:56 ` Junio C Hamano
2018-01-08 20:09 ` Stefan Beller
2018-02-01 19:29 ` [PATCHv3 0/4] blame: (dim rep. metadata lines or fields, decay date coloring) Ævar Arnfjörð Bjarmason
2018-02-01 20:24 ` Stefan Beller
-- strict thread matches above, loose matches on Subject: below --
2017-12-28 21:03 [PATCHv2 " Stefan Beller
2017-12-28 21:03 ` [PATCH 3/4] builtin/blame: add option to color metadata fields separately Stefan Beller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171110011002.10179-4-sbeller@google.com \
--to=sbeller@google.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.