{"thread":{"id":"48351","subject":"[PATCH 0/3] Colorful blame output","startedAt":"2018-04-24T00:09:09Z","lastAt":"2018-04-24T18:05:32Z","messageCount":6,"participants":["Stefan Beller","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"345579","messageId":"20180424000900.175235-1-sbeller@google.com","threadId":"48351","inReplyTo":null,"subject":"[PATCH 0/3] Colorful blame output","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-04-24T00:08:57Z","receivedAt":"2018-04-24T00:09:09Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"This is a revamp of\nhttps://public-inbox.org/git/20180416220955.46163-1-sbeller@google.com/\n\nJunio had some issue with that version, as it would collide config and command\nline options. This is fixed now by introducing another option.\n\nThanks,\nStefan\n\nStefan Beller (3):\n  builtin/blame: dim uninteresting metadata lines\n  builtin/blame: highlight recently changed lines\n  builtin/blame: add new coloring scheme config\n\n Documentation/config.txt |  27 ++++++++\n builtin/blame.c          | 129 +++++++++++++++++++++++++++++++++++++--\n t/t8012-blame-colors.sh  |  48 +++++++++++++++\n 3 files changed, 200 insertions(+), 4 deletions(-)\n create mode 100755 t/t8012-blame-colors.sh\n\n-- \n2.17.0.441.gb46fe60e1d-goog\n\n"},{"id":"345580","messageId":"20180424000900.175235-2-sbeller@google.com","threadId":"48351","inReplyTo":"20180424000900.175235-1-sbeller@google.com","subject":"[PATCH 1/3] builtin/blame: dim uninteresting metadata lines","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-04-24T00:08:58Z","receivedAt":"2018-04-24T00:09:12Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"When using git-blame lots of lines contain redundant information, for\nexample in hunks that consist of multiple lines, the metadata (commit\nname, author, date) are repeated. A reader may not be interested in those,\nso offer an option to color the information that is repeated from the\nprevious line differently. Traditionally, we use CYAN for lines that\nare less interesting than others (e.g. hunk header), so go with that.\n\nThe command line option '--color-lines' will trigger the coloring of\nrepeated lines, and the config option 'color.blame.colorLines' is\nprovided to select the color. Setting the config option doesn't imply\nthat repeated lines are colored. A later patch will introduce a config\nto enable this mode by default.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n Documentation/config.txt |  5 +++++\n builtin/blame.c          | 39 +++++++++++++++++++++++++++++++++++----\n t/t8012-blame-colors.sh  | 19 +++++++++++++++++++\n 3 files changed, 59 insertions(+), 4 deletions(-)\n create mode 100755 t/t8012-blame-colors.sh\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 2659153cb3..9445a3a548 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1218,6 +1218,11 @@ color.status.<slot>::\n \tstatus short-format), or\n \t`unmerged` (files which have unmerged changes).\n \n+color.blame.repeatedLines::\n+\tUse the customized color for the part of git-blame output that\n+\tis repeated meta information per line (such as commit id,\n+\tauthor name, date and timezone). Defaults to cyan.\n+\n color.ui::\n \tThis variable determines the default value for variables such\n \tas `color.diff` and `color.grep` that control the use of color\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex db38c0b307..4d5fc64880 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -7,6 +7,7 @@\n \n #include \"cache.h\"\n #include \"config.h\"\n+#include \"color.h\"\n #include \"builtin.h\"\n #include \"commit.h\"\n #include \"diff.h\"\n@@ -46,6 +47,7 @@ static int xdl_opts;\n static int abbrev = -1;\n static int no_whole_file_rename;\n static int show_progress;\n+static char repeated_meta_color[COLOR_MAXLEN];\n \n static struct date_mode blame_date_mode = { DATE_ISO8601 };\n static size_t blame_date_width;\n@@ -316,10 +318,11 @@ static const char *format_time(timestamp_t time, const char *tz_str,\n #define OUTPUT_PORCELAIN\t010\n #define OUTPUT_SHOW_NAME\t020\n #define OUTPUT_SHOW_NUMBER\t040\n-#define OUTPUT_SHOW_SCORE      0100\n-#define OUTPUT_NO_AUTHOR       0200\n+#define OUTPUT_SHOW_SCORE\t0100\n+#define OUTPUT_NO_AUTHOR\t0200\n #define OUTPUT_SHOW_EMAIL\t0400\n-#define OUTPUT_LINE_PORCELAIN 01000\n+#define OUTPUT_LINE_PORCELAIN\t01000\n+#define OUTPUT_COLOR_LINE\t02000\n \n static void emit_porcelain_details(struct blame_origin *suspect, int repeat)\n {\n@@ -375,6 +378,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int\n \tstruct commit_info ci;\n \tchar hex[GIT_MAX_HEXSZ + 1];\n \tint show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);\n+\tconst char *color = NULL, *reset = NULL;\n \n \tget_commit_info(suspect->commit, &ci, 1);\n \toid_to_hex_r(hex, &suspect->commit->object.oid);\n@@ -384,6 +388,18 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int\n \t\tchar ch;\n \t\tint length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev;\n \n+\t\tif (opt & OUTPUT_COLOR_LINE) {\n+\t\t\tif (cnt > 0) {\n+\t\t\t\tcolor = repeated_meta_color;\n+\t\t\t\treset = GIT_COLOR_RESET;\n+\t\t\t} else  {\n+\t\t\t\tcolor = NULL;\n+\t\t\t\treset = NULL;\n+\t\t\t}\n+\t\t}\n+\t\tif (color)\n+\t\t\tfputs(color, stdout);\n+\n \t\tif (suspect->commit->object.flags & UNINTERESTING) {\n \t\t\tif (blank_boundary)\n \t\t\t\tmemset(hex, ' ', length);\n@@ -433,6 +449,8 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int\n \t\t\tprintf(\" %*d) \",\n \t\t\t       max_digits, ent->lno + 1 + cnt);\n \t\t}\n+\t\tif (reset)\n+\t\t\tfputs(reset, stdout);\n \t\tdo {\n \t\t\tch = *cp++;\n \t\t\tputchar(ch);\n@@ -607,6 +625,12 @@ static int git_blame_config(const char *var, const char *value, void *cb)\n \t\tparse_date_format(value, &blame_date_mode);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"color.blame.repeatedlines\")) {\n+\t\tif (color_parse_mem(value, strlen(value), repeated_meta_color))\n+\t\t\twarning(_(\"invalid color '%s' in color.blame.repeatedLines\"),\n+\t\t\t\tvalue);\n+\t\treturn 0;\n+\t}\n \n \tif (git_diff_heuristic_config(var, value, cb) < 0)\n \t\treturn -1;\n@@ -690,6 +714,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\tOPT_BIT('s', NULL, &output_option, N_(\"Suppress author name and timestamp (Default: off)\"), OUTPUT_NO_AUTHOR),\n \t\tOPT_BIT('e', \"show-email\", &output_option, N_(\"Show author email instead of name (Default: off)\"), OUTPUT_SHOW_EMAIL),\n \t\tOPT_BIT('w', NULL, &xdl_opts, N_(\"Ignore whitespace differences\"), XDF_IGNORE_WHITESPACE),\n+\t\tOPT_BIT(0, \"color-lines\", &output_option, N_(\"color redundant metadata from previous line differently\"), OUTPUT_COLOR_LINE),\n \n \t\t/*\n \t\t * The following two options are parsed by parse_revision_opt()\n@@ -949,8 +974,14 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \n \tblame_coalesce(&sb);\n \n-\tif (!(output_option & OUTPUT_PORCELAIN))\n+\tif (!(output_option & OUTPUT_PORCELAIN)) {\n \t\tfind_alignment(&sb, &output_option);\n+\t\tif (!*repeated_meta_color &&\n+\t\t    (output_option & OUTPUT_COLOR_LINE))\n+\t\t\tstrcpy(repeated_meta_color, GIT_COLOR_CYAN);\n+\t}\n+\tif (output_option & OUTPUT_ANNOTATE_COMPAT)\n+\t\toutput_option &= ~OUTPUT_COLOR_LINE;\n \n \toutput(&sb, output_option);\n \tfree((void *)sb.final_buf);\ndiff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh\nnew file mode 100755\nindex 0000000000..98a22a3c8d\n--- /dev/null\n+++ b/t/t8012-blame-colors.sh\n@@ -0,0 +1,19 @@\n+#!/bin/sh\n+\n+test_description='colored git blame'\n+. ./test-lib.sh\n+\n+PROG='git blame -c'\n+. \"$TEST_DIRECTORY\"/annotate-tests.sh\n+\n+test_expect_success 'colored blame colors contiguous lines' '\n+\tgit -c color.blame.repeatedLines=yellow blame --color-lines --abbrev=12 hello.c >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n+\tgrep \"<YELLOW>\" <actual >darkened &&\n+\tgrep \"(F\" darkened > F.expect &&\n+\tgrep \"(H\" darkened > H.expect &&\n+\ttest_line_count = 2 F.expect &&\n+\ttest_line_count = 3 H.expect\n+'\n+\n+test_done\n-- \n2.17.0.441.gb46fe60e1d-goog\n\n"},{"id":"345581","messageId":"20180424000900.175235-3-sbeller@google.com","threadId":"48351","inReplyTo":"20180424000900.175235-1-sbeller@google.com","subject":"[PATCH 2/3] builtin/blame: highlight recently changed lines","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-04-24T00:08:59Z","receivedAt":"2018-04-24T00:09:16Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Choose a different color for dates and imitate a 'temperature cool down'\ndepending upon age.\n\nOriginally I had planned to have the temperature cool down dependent on\nthe age of the project or file for example, as that might scale better,\nbut that can be added on top of this commit, e.g. instead of giving a\ndate, you could imagine giving a percentage that would be the linearly\ninterpolated between now and the beginning of the file.\n\nSimilarly to the previous patch, this offers the command line option\n'--color-by-age' to enable this mode and the config option\n'color.blame.highlightrecent' to select colors. A later patch will offer\na config option to select the default mode.\n\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n Documentation/config.txt | 17 +++++++++\n builtin/blame.c          | 80 ++++++++++++++++++++++++++++++++++++++--\n t/t8012-blame-colors.sh  | 25 +++++++++++++\n 3 files changed, 118 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 9445a3a548..1496fa4917 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1223,6 +1223,23 @@ color.blame.repeatedLines::\n \tis repeated meta information per line (such as commit id,\n \tauthor name, date and timezone). Defaults to cyan.\n \n+color.blame.highlightRecent::\n+\tThis can be used to color the metadata of a blame line depending\n+\ton age of the line.\n++\n+This setting should be set to a comma-separated list of color and date settings,\n+starting and ending with a color, the dates should be set from oldest to newest.\n+The metadata will be colored given the colors if the the line was introduced\n+before the given timestamp, overwriting older timestamped colors.\n++\n+Instead of an absolute timestamp relative timestamps work as well, e.g.\n+2.weeks.ago is valid to address anything older than 2 weeks.\n++\n+It defaults to 'blue,12 month ago,white,1 month ago,red', which colors\n+everything older than one year blue, recent changes between one month and\n+one year old are kept white, and lines introduced within the last month are\n+colored red.\n+\n color.ui::\n \tThis variable determines the default value for variables such\n \tas `color.diff` and `color.grep` that control the use of color\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 4d5fc64880..d1d469c0b5 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -24,6 +24,7 @@\n #include \"dir.h\"\n #include \"progress.h\"\n #include \"blame.h\"\n+#include \"string-list.h\"\n \n static char blame_usage[] = N_(\"git blame [<options>] [<rev-opts>] [<rev>] [--] <file>\");\n \n@@ -323,6 +324,7 @@ static const char *format_time(timestamp_t time, const char *tz_str,\n #define OUTPUT_SHOW_EMAIL\t0400\n #define OUTPUT_LINE_PORCELAIN\t01000\n #define OUTPUT_COLOR_LINE\t02000\n+#define OUTPUT_SHOW_AGE_WITH_COLOR\t04000\n \n static void emit_porcelain_details(struct blame_origin *suspect, int repeat)\n {\n@@ -370,6 +372,63 @@ static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,\n \t\tputchar('\\n');\n }\n \n+static struct color_field {\n+\ttimestamp_t hop;\n+\tchar col[COLOR_MAXLEN];\n+} *colorfield;\n+static int colorfield_nr, colorfield_alloc;\n+\n+static void parse_color_fields(const char *s)\n+{\n+\tstruct string_list l = STRING_LIST_INIT_DUP;\n+\tstruct string_list_item *item;\n+\tenum { EXPECT_DATE, EXPECT_COLOR } next = EXPECT_COLOR;\n+\n+\tcolorfield_nr = 0;\n+\n+\t/* Ideally this would be stripped and split at the same time? */\n+\tstring_list_split(&l, s, ',', -1);\n+\tALLOC_GROW(colorfield, colorfield_nr + 1, colorfield_alloc);\n+\n+\tfor_each_string_list_item(item, &l) {\n+\t\tswitch (next) {\n+\t\tcase EXPECT_DATE:\n+\t\t\tcolorfield[colorfield_nr].hop = approxidate(item->string);\n+\t\t\tnext = EXPECT_COLOR;\n+\t\t\tcolorfield_nr++;\n+\t\t\tALLOC_GROW(colorfield, colorfield_nr + 1, colorfield_alloc);\n+\t\t\tbreak;\n+\t\tcase EXPECT_COLOR:\n+\t\t\tif (color_parse(item->string, colorfield[colorfield_nr].col))\n+\t\t\t\tdie(_(\"expecting a color: %s\"), item->string);\n+\t\t\tnext = EXPECT_DATE;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (next == EXPECT_COLOR)\n+\t\tdie (_(\"must end with a color\"));\n+\n+\tcolorfield[colorfield_nr].hop = TIME_MAX;\n+}\n+\n+static void setup_default_color_by_age(void)\n+{\n+\tparse_color_fields(\"blue,12 month ago,white,1 month ago,red\");\n+}\n+\n+static void determine_line_heat(struct blame_entry *ent, const char **dest_color)\n+{\n+\tint i = 0;\n+\tstruct commit_info ci;\n+\tget_commit_info(ent->suspect->commit, &ci, 1);\n+\n+\twhile (i < colorfield_nr && ci.author_time > colorfield[i].hop)\n+\t\ti++;\n+\n+\t*dest_color = colorfield[i].col;\n+}\n+\n static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int opt)\n {\n \tint cnt;\n@@ -378,12 +437,19 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int\n \tstruct commit_info ci;\n \tchar hex[GIT_MAX_HEXSZ + 1];\n \tint show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);\n-\tconst char *color = NULL, *reset = NULL;\n+\tconst char *default_color = NULL, *color = NULL, *reset = NULL;\n \n \tget_commit_info(suspect->commit, &ci, 1);\n \toid_to_hex_r(hex, &suspect->commit->object.oid);\n \n \tcp = blame_nth_line(sb, ent->lno);\n+\n+\tif (opt & OUTPUT_SHOW_AGE_WITH_COLOR) {\n+\t\tdetermine_line_heat(ent, &default_color);\n+\t\tcolor = default_color;\n+\t\treset = GIT_COLOR_RESET;\n+\t}\n+\n \tfor (cnt = 0; cnt < ent->num_lines; cnt++) {\n \t\tchar ch;\n \t\tint length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev;\n@@ -393,8 +459,8 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int\n \t\t\t\tcolor = repeated_meta_color;\n \t\t\t\treset = GIT_COLOR_RESET;\n \t\t\t} else  {\n-\t\t\t\tcolor = NULL;\n-\t\t\t\treset = NULL;\n+\t\t\t\tcolor = default_color ? default_color : NULL;\n+\t\t\t\treset = default_color ? GIT_COLOR_RESET : NULL;\n \t\t\t}\n \t\t}\n \t\tif (color)\n@@ -631,6 +697,10 @@ static int git_blame_config(const char *var, const char *value, void *cb)\n \t\t\t\tvalue);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"color.blame.highlightrecent\")) {\n+\t\tparse_color_fields(value);\n+\t\treturn 0;\n+\t}\n \n \tif (git_diff_heuristic_config(var, value, cb) < 0)\n \t\treturn -1;\n@@ -715,6 +785,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\tOPT_BIT('e', \"show-email\", &output_option, N_(\"Show author email instead of name (Default: off)\"), OUTPUT_SHOW_EMAIL),\n \t\tOPT_BIT('w', NULL, &xdl_opts, N_(\"Ignore whitespace differences\"), XDF_IGNORE_WHITESPACE),\n \t\tOPT_BIT(0, \"color-lines\", &output_option, N_(\"color redundant metadata from previous line differently\"), OUTPUT_COLOR_LINE),\n+\t\tOPT_BIT(0, \"color-by-age\", &output_option, N_(\"color lines by age\"), OUTPUT_SHOW_AGE_WITH_COLOR),\n \n \t\t/*\n \t\t * The following two options are parsed by parse_revision_opt()\n@@ -739,6 +810,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \tunsigned int range_i;\n \tlong anchor;\n \n+\tsetup_default_color_by_age();\n \tgit_config(git_blame_config, &output_option);\n \tinit_revisions(&revs, NULL);\n \trevs.date_mode = blame_date_mode;\n@@ -981,7 +1053,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\tstrcpy(repeated_meta_color, GIT_COLOR_CYAN);\n \t}\n \tif (output_option & OUTPUT_ANNOTATE_COMPAT)\n-\t\toutput_option &= ~OUTPUT_COLOR_LINE;\n+\t\toutput_option &= ~(OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR);\n \n \toutput(&sb, output_option);\n \tfree((void *)sb.final_buf);\ndiff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh\nindex 98a22a3c8d..ae9aa79d4e 100755\n--- a/t/t8012-blame-colors.sh\n+++ b/t/t8012-blame-colors.sh\n@@ -16,4 +16,29 @@ test_expect_success 'colored blame colors contiguous lines' '\n \ttest_line_count = 3 H.expect\n '\n \n+test_expect_success 'color by age consistently colors old code' '\n+\tgit blame --color-by-age hello.c >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n+\tgrep \"<BLUE>\" <actual >colored &&\n+\ttest_line_count = 10 colored\n+'\n+\n+test_expect_success 'blame color by age: new code is different' '\n+\tcat >>hello.c <<-EOF &&\n+\t\tvoid qfunc();\n+\tEOF\n+\tgit add hello.c &&\n+\tGIT_AUTHOR_DATE=\"\" git commit -m \"new commit\" &&\n+\n+\tgit -c color.blame.highlightRecent=\"yellow,1 month ago, cyan\" blame --color-by-age hello.c >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n+\n+\tgrep \"<YELLOW>\" <actual >colored &&\n+\ttest_line_count = 10 colored &&\n+\n+\tgrep \"<CYAN>\" <actual >colored &&\n+\ttest_line_count = 1 colored &&\n+\tgrep qfunc colored\n+'\n+\n test_done\n-- \n2.17.0.441.gb46fe60e1d-goog\n\n"},{"id":"345582","messageId":"20180424000900.175235-4-sbeller@google.com","threadId":"48351","inReplyTo":"20180424000900.175235-1-sbeller@google.com","subject":"[PATCH 3/3] builtin/blame: add new coloring scheme config","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-04-24T00:09:00Z","receivedAt":"2018-04-24T00:09:19Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Add a config option that allows selecting the default color scheme for\nblame. The command line still takes precedence over the configuration.\n\nIt is to be seen, how color.ui will integrate with blame coloring.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n Documentation/config.txt |  5 +++++\n builtin/blame.c          | 18 ++++++++++++++++++\n t/t8012-blame-colors.sh  |  4 ++++\n 3 files changed, 27 insertions(+)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 1496fa4917..c03e20cf23 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1240,6 +1240,11 @@ everything older than one year blue, recent changes between one month and\n one year old are kept white, and lines introduced within the last month are\n colored red.\n \n+blame.coloring::\n+\tThis determines the coloring scheme to be applied to blame\n+\toutput. It can be 'repeatedLines', 'highlightRecent',\n+\tor 'none' which is the default.\n+\n color.ui::\n \tThis variable determines the default value for variables such\n \tas `color.diff` and `color.grep` that control the use of color\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex d1d469c0b5..fede1cf1e3 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -49,6 +49,7 @@ static int abbrev = -1;\n static int no_whole_file_rename;\n static int show_progress;\n static char repeated_meta_color[COLOR_MAXLEN];\n+static int coloring_mode;\n \n static struct date_mode blame_date_mode = { DATE_ISO8601 };\n static size_t blame_date_width;\n@@ -702,6 +703,20 @@ static int git_blame_config(const char *var, const char *value, void *cb)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"blame.coloring\")) {\n+\t\tif (!strcmp(value, \"repeatedLines\")) {\n+\t\t\tcoloring_mode |= OUTPUT_COLOR_LINE;\n+\t\t} else if (!strcmp(value, \"highlightRecent\")) {\n+\t\t\tcoloring_mode |= OUTPUT_SHOW_AGE_WITH_COLOR;\n+\t\t} else if (!strcmp(value, \"none\")) {\n+\t\t\tcoloring_mode &= ~(OUTPUT_COLOR_LINE |\n+\t\t\t\t\t    OUTPUT_SHOW_AGE_WITH_COLOR);\n+\t\t} else {\n+\t\t\twarning(_(\"invalid value for blame.coloring\"));\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n \tif (git_diff_heuristic_config(var, value, cb) < 0)\n \t\treturn -1;\n \tif (userdiff_config(var, value) < 0)\n@@ -1046,6 +1061,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \n \tblame_coalesce(&sb);\n \n+\tif (!(output_option & (OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR)))\n+\t\toutput_option |= coloring_mode;\n+\n \tif (!(output_option & OUTPUT_PORCELAIN)) {\n \t\tfind_alignment(&sb, &output_option);\n \t\tif (!*repeated_meta_color &&\ndiff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh\nindex ae9aa79d4e..ed38f74de9 100755\n--- a/t/t8012-blame-colors.sh\n+++ b/t/t8012-blame-colors.sh\n@@ -8,6 +8,8 @@ PROG='git blame -c'\n \n test_expect_success 'colored blame colors contiguous lines' '\n \tgit -c color.blame.repeatedLines=yellow blame --color-lines --abbrev=12 hello.c >actual.raw &&\n+\tgit -c color.blame.repeatedLines=yellow -c blame.coloring=repeatedLines blame --abbrev=12 hello.c >actual.raw.2 &&\n+\ttest_cmp actual.raw actual.raw.2 &&\n \ttest_decode_color <actual.raw >actual &&\n \tgrep \"<YELLOW>\" <actual >darkened &&\n \tgrep \"(F\" darkened > F.expect &&\n@@ -18,6 +20,8 @@ test_expect_success 'colored blame colors contiguous lines' '\n \n test_expect_success 'color by age consistently colors old code' '\n \tgit blame --color-by-age hello.c >actual.raw &&\n+\tgit -c blame.coloring=highlightRecent blame hello.c >actual.raw.2 &&\n+\ttest_cmp actual.raw actual.raw.2 &&\n \ttest_decode_color <actual.raw >actual &&\n \tgrep \"<BLUE>\" <actual >colored &&\n \ttest_line_count = 10 colored\n-- \n2.17.0.441.gb46fe60e1d-goog\n\n"},{"id":"345596","messageId":"xmqqmuxt73tu.fsf@gitster-ct.c.googlers.com","threadId":"48351","inReplyTo":"20180424000900.175235-1-sbeller@google.com","subject":"Re: [PATCH 0/3] Colorful blame output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-24T02:09:33Z","receivedAt":"2018-04-24T02:09:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> This is a revamp of\n> https://public-inbox.org/git/20180416220955.46163-1-sbeller@google.com/\n>\n> Junio had some issue with that version, as it would collide config and command\n> line options. This is fixed now by introducing another option.\n\nHeh, that sounds as if the series was rerolled unnecessarily, only\nbecause I had unreasonable complaints.  I was hoping that issues the\nseries had were fixed, and my involvement was merely that I happened\nto be the one who pointed out first.\n\nIn any case, will replace and take a look at it.  Thanks.\n\n>\n> Thanks,\n> Stefan\n>\n> Stefan Beller (3):\n>   builtin/blame: dim uninteresting metadata lines\n>   builtin/blame: highlight recently changed lines\n>   builtin/blame: add new coloring scheme config\n>\n>  Documentation/config.txt |  27 ++++++++\n>  builtin/blame.c          | 129 +++++++++++++++++++++++++++++++++++++--\n>  t/t8012-blame-colors.sh  |  48 +++++++++++++++\n>  3 files changed, 200 insertions(+), 4 deletions(-)\n>  create mode 100755 t/t8012-blame-colors.sh\n"},{"id":"345657","messageId":"CAGZ79kZ5UuoAGN4dmzE21abyGR9pzkoaQn6BEfgSFDg+N-xT+w@mail.gmail.com","threadId":"48351","inReplyTo":"xmqqmuxt73tu.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 0/3] Colorful blame output","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-04-24T18:05:27Z","receivedAt":"2018-04-24T18:05:32Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Apr 23, 2018 at 7:09 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> This is a revamp of\n>> https://public-inbox.org/git/20180416220955.46163-1-sbeller@google.com/\n>>\n>> Junio had some issue with that version, as it would collide config and command\n>> line options. This is fixed now by introducing another option.\n>\n> Heh, that sounds as if the series was rerolled unnecessarily, only\n> because I had unreasonable complaints.\n\nSorry for that wording, the complaints were of educational nature, so\nI rerolled it.\n\n> I was hoping that issues the\n> series had were fixed, and my involvement was merely that I happened\n> to be the one who pointed out first.\n\nThere were multiple issues (many fixed already), but there was one\noutstanding design bug, so I had to reroll.\n\n>\n> In any case, will replace and take a look at it.  Thanks.\n\nThanks for looking at it,\nStefan\n"}]}