threads / patch / 43364

patchRe: [PATCH] Colourise git-branch output

Subject: Re: [PATCH] Colourise git-branch output

## tl;dr

6 messages between Dec 12, 2006 and Dec 12, 2006. Diffs are folded; open one to read it.

replies: 5people: 3as markdown or json

Andy Parkins· Dec 12, 2006, 06:41 UTC · lore

[PATCH] Colourise git-branch output

I wanted to have a visual indication of which branches are local and which are remote in git-branch -a output; however Junio was concerned that someone might be using the output in a script. This patch addresses the problem by colouring the git-branch output - which in "auto" mode won't be activated.

I've based it off the colouring code for builtin-diff.c; which means there is a branch color configuration variable that needs setting to something before the color will appear.

The colour parameter is "color.branch" rather than "branch.color" to avoid clashing with the default namespace for default branch merge definitions.

This patch chooses green for local, red for remote and bold green for current.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
 builtin-branch.c |   92 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 87 insertions(+), 5 deletions(-)
Show changes to builtin-branch.c +87 −5
diff --git a/builtin-branch.c b/builtin-branch.c
index 3d5cb0e..7c87b8d 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -5,6 +5,7 @@
  * Based on git-branch.sh by Junio C Hamano.
  */
 
+#include "color.h"
 #include "cache.h"
 #include "refs.h"
 #include "commit.h"
@@ -17,6 +18,58 @@ static const char builtin_branch_usage[] =
 static const char *head;
 static unsigned char head_sha1[20];
 
+static int branch_use_color;
+static char branch_colors[][COLOR_MAXLEN] = {
+	"\033[m",	/* reset */
+	"",		/* PLAIN (normal) */
+	"\033[31m",	/* REMOTE (red) */
+	"\033[32m",	/* LOCAL (green) */
+	"\033[1;32m",	/* CURRENT (boldgreen) */
+};
+enum color_branch {
+	COLOR_BRANCH_RESET = 0,
+	COLOR_BRANCH_PLAIN = 1,
+	COLOR_BRANCH_REMOTE = 2,
+	COLOR_BRANCH_LOCAL = 3,
+	COLOR_BRANCH_CURRENT = 4,
+};
+
+static int parse_branch_color_slot(const char *var, int ofs)
+{
+	if (!strcasecmp(var+ofs, "plain"))
+		return COLOR_BRANCH_PLAIN;
+	if (!strcasecmp(var+ofs, "reset"))
+		return COLOR_BRANCH_RESET;
+	if (!strcasecmp(var+ofs, "remote"))
+		return COLOR_BRANCH_REMOTE;
+	if (!strcasecmp(var+ofs, "local"))
+		return COLOR_BRANCH_LOCAL;
+	if (!strcasecmp(var+ofs, "current"))
+		return COLOR_BRANCH_CURRENT;
+	die("bad config variable '%s'", var);
+}
+
+int git_branch_config(const char *var, const char *value)
+{
+	if (!strcmp(var, "color.branch")) {
+		branch_use_color = git_config_colorbool(var, value);
+		return 0;
+	}
+	if (!strncmp(var, "color.branch.", 13)) {
+		int slot = parse_branch_color_slot(var, 13);
+		color_parse(value, var, branch_colors[slot]);
+		return 0;
+	}
+	return git_default_config(var, value);
+}
+
+const char *branch_get_color(enum color_branch ix)
+{
+	if (branch_use_color)
+		return branch_colors[ix];
+	return "";
+}
+
 static int in_merge_bases(const unsigned char *sha1,
 			  struct commit *rev1,
 			  struct commit *rev2)
@@ -183,6 +236,7 @@ static void print_ref_list(int kinds, int verbose, int abbrev)
 	int i;
 	char c;
 	struct ref_list ref_list;
+	int color;
 
 	memset(&ref_list, 0, sizeof(ref_list));
 	ref_list.kinds = kinds;
@@ -191,18 +245,38 @@ static void print_ref_list(int kinds, int verbose, int abbrev)
 	qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
 
 	for (i = 0; i < ref_list.index; i++) {
+		switch( ref_list.list[i].kind ) {
+			case REF_LOCAL_BRANCH:
+				color = COLOR_BRANCH_LOCAL;
+				break;
+			case REF_REMOTE_BRANCH:
+				color = COLOR_BRANCH_REMOTE;
+				break;
+			default:
+				color = COLOR_BRANCH_PLAIN;
+				break;
+		}
+
 		c = ' ';
 		if (ref_list.list[i].kind == REF_LOCAL_BRANCH &&
-				!strcmp(ref_list.list[i].name, head))
+				!strcmp(ref_list.list[i].name, head)) {
 			c = '*';
+			color = COLOR_BRANCH_CURRENT;
+		}
 
 		if (verbose) {
-			printf("%c %-*s", c, ref_list.maxwidth,
-			       ref_list.list[i].name);
+			printf("%c %s%-*s%s", c,
+					branch_get_color(color),
+					ref_list.maxwidth,
+					ref_list.list[i].name,
+					branch_get_color(COLOR_BRANCH_RESET));
 			print_ref_info(ref_list.list[i].sha1, abbrev);
 		}
 		else
-			printf("%c %s\n", c, ref_list.list[i].name);
+			printf("%c %s%s%s\n", c,
+					branch_get_color(color),
+					ref_list.list[i].name,
+					branch_get_color(COLOR_BRANCH_RESET));
 	}
 
 	free_ref_list(&ref_list);
@@ -253,7 +327,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	int kinds = REF_LOCAL_BRANCH;
 	int i;
 
-	git_config(git_default_config);
+	git_config(git_branch_config);
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
@@ -297,6 +371,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			verbose = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--color")) {
+			branch_use_color = 1;
+			continue;
+		}
+		if (!strcmp(arg, "--no-color")) {
+			branch_use_color = 0;
+			continue;
+		}
 		usage(builtin_branch_usage);
 	}
 
-- 
1.4.4.1.geeee8
Johannes Sixt· Dec 12, 2006, 08:46 UTC · re: Andy Parkins · lore
Andy Parkins wrote:
> This patch chooses green for local, red for remote and bold green for
> current.

Sorry for chiming in so late, but red and green are usually poor choices since red-green color-blindness is surprisingly frequent...

Maybe its sufficient to have just the remote branches (dark-)red, and the rest in the default color, with the current branch bold?

-- Hannes
Junio C Hamano· Dec 12, 2006, 10:10 UTC · re: Johannes Sixt · lore
Johannes Sixt <J.Sixt@eudaptics.com> writes:
Show 9 quoted lines
> Andy Parkins wrote:
>> This patch chooses green for local, red for remote and bold green for
>> current.
>
> Sorry for chiming in so late, but red and green are usually poor choices
> since red-green color-blindness is surprisingly frequent...
>
> Maybe its sufficient to have just the remote branches (dark-)red, and
> the rest in the default color, with the current branch bold?

Even without red-green blindness issue, I think that makes sense. colored-diff uses green/red for added/deleted but that is shown against the context in plain. A sane thing to do for branch listing would be to show the usual case (i.e. local) in plain and show the remote ones differently.

Something like this on top of Andy's?

If we keep '*' prefix for the current one, I do not see a reason to show it in a different color from other local branches, by the way, but I did not go that far in this patch.

---
Show changes to builtin-branch.c +2 −2
diff --git a/builtin-branch.c b/builtin-branch.c
index 7c87b8d..d1c243d 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -23,8 +23,8 @@ static char branch_colors[][COLOR_MAXLEN] = {
 	"\033[m",	/* reset */
 	"",		/* PLAIN (normal) */
 	"\033[31m",	/* REMOTE (red) */
-	"\033[32m",	/* LOCAL (green) */
-	"\033[1;32m",	/* CURRENT (boldgreen) */
+	"",		/* LOCAL (normal) */
+	"\033[32m",	/* CURRENT (green) */
 };
 enum color_branch {
 	COLOR_BRANCH_RESET = 0,
Andy Parkins· Dec 12, 2006, 11:03 UTC · re: Junio C Hamano · lore
On Tuesday 2006 December 12 10:10, Junio C Hamano wrote:
> Even without red-green blindness issue, I think that makes
> sense.  colored-diff uses green/red for added/deleted but that

I certainly don't have any objection. For me, the use of colour is not to make things look pretty it's to give visual queues.

> is shown against the context in plain.  A sane thing to do for
> branch listing would be to show the usual case (i.e. local) in
> plain and show the remote ones differently.

The only reason I picked red and green was to indicate "can be checked out" and "cannot be checked out". However, when git eventually allows arbitrary commits to be checked out that green/red, can/can't distinction will be meaningless anyway.

> +	"",		/* LOCAL (normal) */
> +	"\033[32m",	/* CURRENT (green) */

In keeping with the "don't use green" idea - can I suggest just bold normal for the CURRENT? That way there is the most minimal use of colour for the default git-branch output, but still retaining a visual indicator.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
Junio C Hamano· Dec 12, 2006, 18:43 UTC · re: Andy Parkins · lore
Andy Parkins <andyparkins@gmail.com> writes:
Show 6 quoted lines
>> +	"",		/* LOCAL (normal) */
>> +	"\033[32m",	/* CURRENT (green) */
>
> In keeping with the "don't use green" idea - can I suggest just bold normal 
> for the CURRENT?  That way there is the most minimal use of colour for the 
> default git-branch output, but still retaining a visual indicator.
I do not have strong preference either way.

The CURRENT is highlighted with '*' so I think we certainly can lose green and even go vanilla. I only tried to avoid bold because no built-in default coloring currently use it, and in the past I've worked with terminals that do not have enough contrast between normal and bold and for some people that might become an issue.

Junio C Hamano· Dec 12, 2006, 18:43 UTC · re: Andy Parkins · lore
Andy Parkins <andyparkins@gmail.com> writes:
> The colour parameter is "color.branch" rather than "branch.color" to
> avoid clashing with the default namespace for default branch merge
> definitions.
Very nice.
Show 25 quoted lines
>  		c = ' ';
>  		if (ref_list.list[i].kind == REF_LOCAL_BRANCH &&
> -				!strcmp(ref_list.list[i].name, head))
> +				!strcmp(ref_list.list[i].name, head)) {
>  			c = '*';
> +			color = COLOR_BRANCH_CURRENT;
> +		}
>  
>  		if (verbose) {
> -			printf("%c %-*s", c, ref_list.maxwidth,
> -			       ref_list.list[i].name);
> +			printf("%c %s%-*s%s", c,
> +					branch_get_color(color),
> +					ref_list.maxwidth,
> +					ref_list.list[i].name,
> +					branch_get_color(COLOR_BRANCH_RESET));
>  			print_ref_info(ref_list.list[i].sha1, abbrev);
>  		}
>  		else
> -			printf("%c %s\n", c, ref_list.list[i].name);
> +			printf("%c %s%s%s\n", c,
> +					branch_get_color(color),
> +					ref_list.list[i].name,
> +					branch_get_color(COLOR_BRANCH_RESET));
>  	}

Now this makes me wonder if under output coloring we would still want the two-space indent and '*' prefix.

← back to recent threads