{"thread":{"id":"4498","subject":"[PATCH] diff options: add --color","startedAt":"2006-06-13T16:45:44Z","lastAt":"2006-06-13T16:45:44Z","messageCount":1,"participants":["Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"21723","messageId":"Pine.LNX.4.63.0606131845120.29606@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4498","inReplyTo":null,"subject":"[PATCH] diff options: add --color","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-06-13T16:45:44Z","receivedAt":"2006-06-13T16:45:44Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis patch is a slightly adjusted version of Junio's patch:\nhttp://www.gelato.unsw.edu.au/archives/git/0604/19354.html\n\nHowever, instead of using a config variable, this patch makes it available\nas a diff option.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n diff.c  |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------\n diff.h  |    3 ++\n pager.c |    2 +-\n 3 files changed, 73 insertions(+), 11 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 9e9cfc8..bc32a4a 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -25,6 +25,20 @@ int git_diff_config(const char *var, con\n \treturn git_default_config(var, value);\n }\n \n+enum color_diff {\n+\tDIFF_PLAIN = 0,\n+\tDIFF_METAINFO = 1,\n+\tDIFF_FILE_OLD = 2,\n+\tDIFF_FILE_NEW = 3,\n+};\n+\n+static const char *diff_colors[] = {\n+\t\"\\033[0;0m\",\n+\t\"\\033[1;35m\",\n+\t\"\\033[1;31m\",\n+\t\"\\033[1;34m\",\n+};\n+\n static char *quote_one(const char *str)\n {\n \tint needlen;\n@@ -177,23 +191,54 @@ static int fill_mmfile(mmfile_t *mf, str\n }\n \n struct emit_callback {\n+\tstruct xdiff_emit_state xm;\n+\tint nparents, color_diff;\n \tconst char **label_path;\n };\n \n-static int fn_out(void *priv, mmbuffer_t *mb, int nbuf)\n+static inline void color_diff(int diff_use_color, enum color_diff ix)\n+{\n+\tif (diff_use_color)\n+\t\tfputs(diff_colors[ix], stdout);\n+}\n+\n+static void fn_out_consume(void *priv, char *line, unsigned long len)\n {\n \tint i;\n \tstruct emit_callback *ecbdata = priv;\n \n \tif (ecbdata->label_path[0]) {\n+\t\tcolor_diff(ecbdata->color_diff, DIFF_METAINFO);\n \t\tprintf(\"--- %s\\n\", ecbdata->label_path[0]);\n+\t\tcolor_diff(ecbdata->color_diff, DIFF_METAINFO);\n \t\tprintf(\"+++ %s\\n\", ecbdata->label_path[1]);\n \t\tecbdata->label_path[0] = ecbdata->label_path[1] = NULL;\n \t}\n-\tfor (i = 0; i < nbuf; i++)\n-\t\tif (!fwrite(mb[i].ptr, mb[i].size, 1, stdout))\n-\t\t\treturn -1;\n-\treturn 0;\n+\n+\t/* This is not really necessary for now because\n+\t * this codepath only deals with two-way diffs.\n+\t */\n+\tfor (i = 0; i < len && line[i] == '@'; i++)\n+\t\t;\n+\tif (2 <= i && i < len && line[i] == ' ') {\n+\t\tecbdata->nparents = i - 1;\n+\t\tcolor_diff(ecbdata->color_diff, DIFF_METAINFO);\n+\t}\n+\telse if (len < ecbdata->nparents)\n+\t\tcolor_diff(ecbdata->color_diff, DIFF_PLAIN);\n+\telse {\n+\t\tint nparents = ecbdata->nparents;\n+\t\tint color = DIFF_PLAIN;\n+\t\tfor (i = 0; i < nparents && len; i++) {\n+\t\t\tif (line[i] == '-')\n+\t\t\t\tcolor = DIFF_FILE_OLD;\n+\t\t\telse if (line[i] == '+')\n+\t\t\t\tcolor = DIFF_FILE_NEW;\n+\t\t}\n+\t\tcolor_diff(ecbdata->color_diff, color);\n+\t}\n+\tfwrite(line, len, 1, stdout);\n+\tcolor_diff(ecbdata->color_diff, DIFF_PLAIN);\n }\n \n static char *pprint_rename(const char *a, const char *b)\n@@ -549,25 +594,35 @@ static void builtin_diff(const char *nam\n \tb_two = quote_two(\"b/\", name_b);\n \tlbl[0] = DIFF_FILE_VALID(one) ? a_one : \"/dev/null\";\n \tlbl[1] = DIFF_FILE_VALID(two) ? b_two : \"/dev/null\";\n+\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \tprintf(\"diff --git %s %s\\n\", a_one, b_two);\n \tif (lbl[0][0] == '/') {\n \t\t/* /dev/null */\n+\t\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \t\tprintf(\"new file mode %06o\\n\", two->mode);\n-\t\tif (xfrm_msg && xfrm_msg[0])\n+\t\tif (xfrm_msg && xfrm_msg[0]) {\n+\t\t\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \t\t\tputs(xfrm_msg);\n+\t\t}\n \t}\n \telse if (lbl[1][0] == '/') {\n \t\tprintf(\"deleted file mode %06o\\n\", one->mode);\n-\t\tif (xfrm_msg && xfrm_msg[0])\n+\t\tif (xfrm_msg && xfrm_msg[0]) {\n+\t\t\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \t\t\tputs(xfrm_msg);\n+\t\t}\n \t}\n \telse {\n \t\tif (one->mode != two->mode) {\n+\t\t\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \t\t\tprintf(\"old mode %06o\\n\", one->mode);\n+\t\t\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \t\t\tprintf(\"new mode %06o\\n\", two->mode);\n \t\t}\n-\t\tif (xfrm_msg && xfrm_msg[0])\n+\t\tif (xfrm_msg && xfrm_msg[0]) {\n+\t\t\tcolor_diff(o->color_diff, DIFF_METAINFO);\n \t\t\tputs(xfrm_msg);\n+\t\t}\n \t\t/*\n \t\t * we do not run diff between different kind\n \t\t * of objects.\n@@ -575,6 +630,7 @@ static void builtin_diff(const char *nam\n \t\tif ((one->mode ^ two->mode) & S_IFMT)\n \t\t\tgoto free_ab_and_return;\n \t\tif (complete_rewrite) {\n+\t\t\tcolor_diff(o->color_diff, DIFF_PLAIN);\n \t\t\temit_rewrite_diff(name_a, name_b, one, two);\n \t\t\tgoto free_ab_and_return;\n \t\t}\n@@ -602,7 +658,9 @@ static void builtin_diff(const char *nam\n \t\txdemitcb_t ecb;\n \t\tstruct emit_callback ecbdata;\n \n+\t\tmemset(&ecbdata, 0, sizeof(ecbdata));\n \t\tecbdata.label_path = lbl;\n+\t\tecbdata.color_diff = o->color_diff;\n \t\txpp.flags = XDF_NEED_MINIMAL;\n \t\txecfg.ctxlen = o->context;\n \t\txecfg.flags = XDL_EMIT_FUNCNAMES;\n@@ -612,8 +670,9 @@ static void builtin_diff(const char *nam\n \t\t\txecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);\n \t\telse if (!strncmp(diffopts, \"-u\", 2))\n \t\t\txecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);\n-\t\tecb.outf = fn_out;\n+\t\tecb.outf = xdiff_outf;\n \t\tecb.priv = &ecbdata;\n+\t\tecbdata.xm.consume = fn_out_consume;\n \t\txdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);\n \t}\n \n@@ -1456,6 +1515,8 @@ int diff_opt_parse(struct diff_options *\n \t\telse if (40 < options->abbrev)\n \t\t\toptions->abbrev = 40;\n \t}\n+\telse if (!strcmp(arg, \"--color\"))\n+\t\toptions->color_diff = 1;\n \telse\n \t\treturn 0;\n \treturn 1;\ndiff --git a/diff.h b/diff.h\nindex 99838e6..2b821df 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -32,7 +32,8 @@ struct diff_options {\n \t\t full_index:1,\n \t\t silent_on_remove:1,\n \t\t find_copies_harder:1,\n-\t\t summary:1;\n+\t\t summary:1,\n+\t\t color_diff:1;\n \tint context;\n \tint break_opt;\n \tint detect_rename;\ndiff --git a/pager.c b/pager.c\nindex 9a30939..2d186e8 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -46,7 +46,7 @@ void setup_pager(void)\n \tclose(fd[0]);\n \tclose(fd[1]);\n \n-\tsetenv(\"LESS\", \"-S\", 0);\n+\tsetenv(\"LESS\", \"-RS\", 0);\n \trun_pager(pager);\n \tdie(\"unable to execute pager '%s'\", pager);\n \texit(255);\n-- \n1.4.0.gcaba-dirty\n"}]}