# Re: [PATCH] Colourise git-branch output

6 messages from 2006-12-12 to 2006-12-12. Participants: Junio C Hamano, Johannes Sixt, Andy Parkins.
Thread: https://gitlist.dev/t/43364

## Andy Parkins, 2006-12-12 06:41

Subject: [PATCH] Colourise git-branch output
Message-ID: <200612120641.52556.andyparkins@gmail.com>
URL: https://gitlist.dev/e/200612120641.52556.andyparkins%40gmail.com

```
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(-)

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, 2006-12-12 08:46

Subject: Re: [PATCH] Colourise git-branch output
Message-ID: <457E6C65.4B6D131@eudaptics.com>
URL: https://gitlist.dev/e/457E6C65.4B6D131%40eudaptics.com
In-Reply-To: <200612120641.52556.andyparkins@gmail.com>

```
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, 2006-12-12 10:10

Subject: Re: [PATCH] Colourise git-branch output
Message-ID: <7vpsapwhl2.fsf@assigned-by-dhcp.cox.net>
URL: https://gitlist.dev/e/7vpsapwhl2.fsf%40assigned-by-dhcp.cox.net
In-Reply-To: <457E6C65.4B6D131@eudaptics.com>

```
Johannes Sixt <J.Sixt@eudaptics.com> writes:

> 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.

---
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, 2006-12-12 11:03

Subject: Re: [PATCH] Colourise git-branch output
Message-ID: <200612121103.31110.andyparkins@gmail.com>
URL: https://gitlist.dev/e/200612121103.31110.andyparkins%40gmail.com
In-Reply-To: <7vpsapwhl2.fsf@assigned-by-dhcp.cox.net>

```
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, 2006-12-12 18:43

Subject: Re: [PATCH] Colourise git-branch output
Message-ID: <7vpsapuf8i.fsf@assigned-by-dhcp.cox.net>
URL: https://gitlist.dev/e/7vpsapuf8i.fsf%40assigned-by-dhcp.cox.net
In-Reply-To: <200612120641.52556.andyparkins@gmail.com>

```
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.

>  		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.

```

## Junio C Hamano, 2006-12-12 18:43

Subject: Re: [PATCH] Colourise git-branch output
Message-ID: <7vk60xuf8h.fsf@assigned-by-dhcp.cox.net>
URL: https://gitlist.dev/e/7vk60xuf8h.fsf%40assigned-by-dhcp.cox.net
In-Reply-To: <200612121103.31110.andyparkins@gmail.com>

```
Andy Parkins <andyparkins@gmail.com> writes:

>> +	"",		/* 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.

```
