{"thread":{"id":"4873","subject":"[PATCH] diff: Support both attributes and colors","startedAt":"2006-07-13T16:06:12Z","lastAt":"2006-07-13T16:06:12Z","messageCount":1,"participants":["Timo Hirvonen"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"23768","messageId":"20060713190612.ee66dfba.tihirvon@gmail.com","threadId":"4873","inReplyTo":null,"subject":"[PATCH] diff: Support both attributes and colors","fromName":"Timo Hirvonen","fromEmail":"tihirvon@gmail.com","sentAt":"2006-07-13T16:06:12Z","receivedAt":"2006-07-13T16:06:12Z","isPatch":true,"sender":{"key":"tihirvon@gmail.com","avatar":null},"body":"Make it possible to set both colors and a attribute for diff colors.\nBackground colors are supported too.\n\nSyntax is now:\n\n\t[attr] [fg [bg]]\n\t[fg [bg]] [attr]\n\nEmpty value is same as \"normal normal\", ie use default colors.  The new\nsyntax is backwards compatible.\n\nSigned-off-by: Timo Hirvonen <tihirvon@gmail.com>\n---\n diff.c |  164 ++++++++++++++++++++++++++++++++++++++++++----------------------\n 1 files changed, 107 insertions(+), 57 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex a007019..a9118a9 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -26,30 +26,14 @@ enum color_diff {\n \tDIFF_FILE_NEW = 5,\n };\n \n-#define COLOR_NORMAL  \"\"\n-#define COLOR_BOLD    \"\\033[1m\"\n-#define COLOR_DIM     \"\\033[2m\"\n-#define COLOR_UL      \"\\033[4m\"\n-#define COLOR_BLINK   \"\\033[5m\"\n-#define COLOR_REVERSE \"\\033[7m\"\n-#define COLOR_RESET   \"\\033[m\"\n-\n-#define COLOR_BLACK   \"\\033[30m\"\n-#define COLOR_RED     \"\\033[31m\"\n-#define COLOR_GREEN   \"\\033[32m\"\n-#define COLOR_YELLOW  \"\\033[33m\"\n-#define COLOR_BLUE    \"\\033[34m\"\n-#define COLOR_MAGENTA \"\\033[35m\"\n-#define COLOR_CYAN    \"\\033[36m\"\n-#define COLOR_WHITE   \"\\033[37m\"\n-\n-static const char *diff_colors[] = {\n-\tCOLOR_RESET,\n-\tCOLOR_NORMAL,\n-\tCOLOR_BOLD,\n-\tCOLOR_CYAN,\n-\tCOLOR_RED,\n-\tCOLOR_GREEN\n+/* \"\\033[1;30;47m\\0\" is 11 bytes */\n+static char diff_colors[][16] = {\n+\t\"\\033[m\",\t/* reset */\n+\t\"\",\t\t/* normal */\n+\t\"\\033[1m\",\t/* bold */\n+\t\"\\033[36m\",\t/* cyan */\n+\t\"\\033[31m\",\t/* red */\n+\t\"\\033[32m\"\t/* green */\n };\n \n static int parse_diff_color_slot(const char *var, int ofs)\n@@ -67,38 +51,104 @@ static int parse_diff_color_slot(const c\n \tdie(\"bad config variable '%s'\", var);\n }\n \n-static const char *parse_diff_color_value(const char *value, const char *var)\n-{\n-\tif (!strcasecmp(value, \"normal\"))\n-\t\treturn COLOR_NORMAL;\n-\tif (!strcasecmp(value, \"bold\"))\n-\t\treturn COLOR_BOLD;\n-\tif (!strcasecmp(value, \"dim\"))\n-\t\treturn COLOR_DIM;\n-\tif (!strcasecmp(value, \"ul\"))\n-\t\treturn COLOR_UL;\n-\tif (!strcasecmp(value, \"blink\"))\n-\t\treturn COLOR_BLINK;\n-\tif (!strcasecmp(value, \"reverse\"))\n-\t\treturn COLOR_REVERSE;\n-\tif (!strcasecmp(value, \"reset\"))\n-\t\treturn COLOR_RESET;\n-\tif (!strcasecmp(value, \"black\"))\n-\t\treturn COLOR_BLACK;\n-\tif (!strcasecmp(value, \"red\"))\n-\t\treturn COLOR_RED;\n-\tif (!strcasecmp(value, \"green\"))\n-\t\treturn COLOR_GREEN;\n-\tif (!strcasecmp(value, \"yellow\"))\n-\t\treturn COLOR_YELLOW;\n-\tif (!strcasecmp(value, \"blue\"))\n-\t\treturn COLOR_BLUE;\n-\tif (!strcasecmp(value, \"magenta\"))\n-\t\treturn COLOR_MAGENTA;\n-\tif (!strcasecmp(value, \"cyan\"))\n-\t\treturn COLOR_CYAN;\n-\tif (!strcasecmp(value, \"white\"))\n-\t\treturn COLOR_WHITE;\n+static int parse_color(const char *name, int len)\n+{\n+\tstatic const char * const color_names[] = {\n+\t\t\"normal\", \"black\", \"red\", \"green\", \"yellow\",\n+\t\t\"blue\", \"magenta\", \"cyan\", \"white\"\n+\t};\n+\tint i;\n+\tfor (i = 0; i < ARRAY_SIZE(color_names); i++) {\n+\t\tconst char *str = color_names[i];\n+\t\tif (!strncasecmp(name, str, len) && !str[len])\n+\t\t\treturn i - 1;\n+\t}\n+\treturn -2;\n+}\n+\n+static int parse_attr(const char *name, int len)\n+{\n+\tstatic const int attr_values[] = { 1, 2, 4, 5, 7 };\n+\tstatic const char * const attr_names[] = {\n+\t\t\"bold\", \"dim\", \"ul\", \"blink\", \"reverse\"\n+\t};\n+\tint i;\n+\tfor (i = 0; i < ARRAY_SIZE(attr_names); i++) {\n+\t\tconst char *str = attr_names[i];\n+\t\tif (!strncasecmp(name, str, len) && !str[len])\n+\t\t\treturn attr_values[i];\n+\t}\n+\treturn -1;\n+}\n+\n+static void parse_diff_color_value(const char *value, const char *var, char *dst)\n+{\n+\tconst char *ptr = value;\n+\tint attr = -1;\n+\tint fg = -2;\n+\tint bg = -2;\n+\n+\tif (!strcasecmp(value, \"reset\")) {\n+\t\tstrcpy(dst, \"\\033[m\");\n+\t\treturn;\n+\t}\n+\n+\t/* [fg [bg]] [attr] */\n+\twhile (*ptr) {\n+\t\tconst char *word = ptr;\n+\t\tint val, len = 0;\n+\n+\t\twhile (word[len] && !isspace(word[len]))\n+\t\t\tlen++;\n+\n+\t\tptr = word + len;\n+\t\twhile (*ptr && isspace(*ptr))\n+\t\t\tptr++;\n+\n+\t\tval = parse_color(word, len);\n+\t\tif (val >= -1) {\n+\t\t\tif (fg == -2) {\n+\t\t\t\tfg = val;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (bg == -2) {\n+\t\t\t\tbg = val;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tgoto bad;\n+\t\t}\n+\t\tval = parse_attr(word, len);\n+\t\tif (val < 0 || attr != -1)\n+\t\t\tgoto bad;\n+\t\tattr = val;\n+\t}\n+\n+\tif (attr >= 0 || fg >= 0 || bg >= 0) {\n+\t\tint sep = 0;\n+\n+\t\t*dst++ = '\\033';\n+\t\t*dst++ = '[';\n+\t\tif (attr >= 0) {\n+\t\t\t*dst++ = '0' + attr;\n+\t\t\tsep++;\n+\t\t}\n+\t\tif (fg >= 0) {\n+\t\t\tif (sep++)\n+\t\t\t\t*dst++ = ';';\n+\t\t\t*dst++ = '3';\n+\t\t\t*dst++ = '0' + fg;\n+\t\t}\n+\t\tif (bg >= 0) {\n+\t\t\tif (sep++)\n+\t\t\t\t*dst++ = ';';\n+\t\t\t*dst++ = '4';\n+\t\t\t*dst++ = '0' + bg;\n+\t\t}\n+\t\t*dst++ = 'm';\n+\t}\n+\t*dst = 0;\n+\treturn;\n+bad:\n \tdie(\"bad config value '%s' for variable '%s'\", value, var);\n }\n \n@@ -145,7 +195,7 @@ int git_diff_ui_config(const char *var, \n \t}\n \tif (!strncmp(var, \"diff.color.\", 11)) {\n \t\tint slot = parse_diff_color_slot(var, 11);\n-\t\tdiff_colors[slot] = parse_diff_color_value(value, var);\n+\t\tparse_diff_color_value(value, var, diff_colors[slot]);\n \t\treturn 0;\n \t}\n \treturn git_default_config(var, value);\n-- \n1.4.1.gd0c9d-dirty\n"}]}