[PATCH] diff: Support both attributes and colors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Make it possible to set both colors and a attribute for diff colors.
Background colors are supported too.

Syntax is now:

	[attr] [fg [bg]]
	[fg [bg]] [attr]

Empty value is same as "normal normal", ie use default colors.  The new
syntax is backwards compatible.

Signed-off-by: Timo Hirvonen <tihirvon@xxxxxxxxx>
---
 diff.c |  164 ++++++++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 107 insertions(+), 57 deletions(-)

diff --git a/diff.c b/diff.c
index a007019..a9118a9 100644
--- a/diff.c
+++ b/diff.c
@@ -26,30 +26,14 @@ enum color_diff {
 	DIFF_FILE_NEW = 5,
 };
 
-#define COLOR_NORMAL  ""
-#define COLOR_BOLD    "\033[1m"
-#define COLOR_DIM     "\033[2m"
-#define COLOR_UL      "\033[4m"
-#define COLOR_BLINK   "\033[5m"
-#define COLOR_REVERSE "\033[7m"
-#define COLOR_RESET   "\033[m"
-
-#define COLOR_BLACK   "\033[30m"
-#define COLOR_RED     "\033[31m"
-#define COLOR_GREEN   "\033[32m"
-#define COLOR_YELLOW  "\033[33m"
-#define COLOR_BLUE    "\033[34m"
-#define COLOR_MAGENTA "\033[35m"
-#define COLOR_CYAN    "\033[36m"
-#define COLOR_WHITE   "\033[37m"
-
-static const char *diff_colors[] = {
-	COLOR_RESET,
-	COLOR_NORMAL,
-	COLOR_BOLD,
-	COLOR_CYAN,
-	COLOR_RED,
-	COLOR_GREEN
+/* "\033[1;30;47m\0" is 11 bytes */
+static char diff_colors[][16] = {
+	"\033[m",	/* reset */
+	"",		/* normal */
+	"\033[1m",	/* bold */
+	"\033[36m",	/* cyan */
+	"\033[31m",	/* red */
+	"\033[32m"	/* green */
 };
 
 static int parse_diff_color_slot(const char *var, int ofs)
@@ -67,38 +51,104 @@ static int parse_diff_color_slot(const c
 	die("bad config variable '%s'", var);
 }
 
-static const char *parse_diff_color_value(const char *value, const char *var)
-{
-	if (!strcasecmp(value, "normal"))
-		return COLOR_NORMAL;
-	if (!strcasecmp(value, "bold"))
-		return COLOR_BOLD;
-	if (!strcasecmp(value, "dim"))
-		return COLOR_DIM;
-	if (!strcasecmp(value, "ul"))
-		return COLOR_UL;
-	if (!strcasecmp(value, "blink"))
-		return COLOR_BLINK;
-	if (!strcasecmp(value, "reverse"))
-		return COLOR_REVERSE;
-	if (!strcasecmp(value, "reset"))
-		return COLOR_RESET;
-	if (!strcasecmp(value, "black"))
-		return COLOR_BLACK;
-	if (!strcasecmp(value, "red"))
-		return COLOR_RED;
-	if (!strcasecmp(value, "green"))
-		return COLOR_GREEN;
-	if (!strcasecmp(value, "yellow"))
-		return COLOR_YELLOW;
-	if (!strcasecmp(value, "blue"))
-		return COLOR_BLUE;
-	if (!strcasecmp(value, "magenta"))
-		return COLOR_MAGENTA;
-	if (!strcasecmp(value, "cyan"))
-		return COLOR_CYAN;
-	if (!strcasecmp(value, "white"))
-		return COLOR_WHITE;
+static int parse_color(const char *name, int len)
+{
+	static const char * const color_names[] = {
+		"normal", "black", "red", "green", "yellow",
+		"blue", "magenta", "cyan", "white"
+	};
+	int i;
+	for (i = 0; i < ARRAY_SIZE(color_names); i++) {
+		const char *str = color_names[i];
+		if (!strncasecmp(name, str, len) && !str[len])
+			return i - 1;
+	}
+	return -2;
+}
+
+static int parse_attr(const char *name, int len)
+{
+	static const int attr_values[] = { 1, 2, 4, 5, 7 };
+	static const char * const attr_names[] = {
+		"bold", "dim", "ul", "blink", "reverse"
+	};
+	int i;
+	for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
+		const char *str = attr_names[i];
+		if (!strncasecmp(name, str, len) && !str[len])
+			return attr_values[i];
+	}
+	return -1;
+}
+
+static void parse_diff_color_value(const char *value, const char *var, char *dst)
+{
+	const char *ptr = value;
+	int attr = -1;
+	int fg = -2;
+	int bg = -2;
+
+	if (!strcasecmp(value, "reset")) {
+		strcpy(dst, "\033[m");
+		return;
+	}
+
+	/* [fg [bg]] [attr] */
+	while (*ptr) {
+		const char *word = ptr;
+		int val, len = 0;
+
+		while (word[len] && !isspace(word[len]))
+			len++;
+
+		ptr = word + len;
+		while (*ptr && isspace(*ptr))
+			ptr++;
+
+		val = parse_color(word, len);
+		if (val >= -1) {
+			if (fg == -2) {
+				fg = val;
+				continue;
+			}
+			if (bg == -2) {
+				bg = val;
+				continue;
+			}
+			goto bad;
+		}
+		val = parse_attr(word, len);
+		if (val < 0 || attr != -1)
+			goto bad;
+		attr = val;
+	}
+
+	if (attr >= 0 || fg >= 0 || bg >= 0) {
+		int sep = 0;
+
+		*dst++ = '\033';
+		*dst++ = '[';
+		if (attr >= 0) {
+			*dst++ = '0' + attr;
+			sep++;
+		}
+		if (fg >= 0) {
+			if (sep++)
+				*dst++ = ';';
+			*dst++ = '3';
+			*dst++ = '0' + fg;
+		}
+		if (bg >= 0) {
+			if (sep++)
+				*dst++ = ';';
+			*dst++ = '4';
+			*dst++ = '0' + bg;
+		}
+		*dst++ = 'm';
+	}
+	*dst = 0;
+	return;
+bad:
 	die("bad config value '%s' for variable '%s'", value, var);
 }
 
@@ -145,7 +195,7 @@ int git_diff_ui_config(const char *var, 
 	}
 	if (!strncmp(var, "diff.color.", 11)) {
 		int slot = parse_diff_color_slot(var, 11);
-		diff_colors[slot] = parse_diff_color_value(value, var);
+		parse_diff_color_value(value, var, diff_colors[slot]);
 		return 0;
 	}
 	return git_default_config(var, value);
-- 
1.4.1.gd0c9d-dirty

-
: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]