studog
studog

Reputation: 1088

Git colors: How do I set colors for the upstream branch _status_ in “git branch -vv”?

My question is not a duplicate of this question; I want to know how to color the gone part of the branch status:

user@host:~/devel/repo$ git branch -vv
user/feature           3ffcd496f [github/user/feature: gone] Feature complete

I can't find any references to this capability in my current git version 2.17.1 man pages, so I'm guessing it doesn't exist yet. Googling didn't turn up anything relevant either.

I'm finding that the status can sometimes get lost in the wall of text when there are a lot of branches. I'd like it to stand out a bit more.

I could use one of the answers from this question but given how context-sensitive the information I want to colour is most of those answers will get pretty hairy pretty quickly. For example, colorit doesn't appear to be able to colour a subset of the matched regexp, so colouring just the gone in the upstream status isn't possible and unluckily-named branches will get "randomly" coloured.

git is the source of the context so is the natural choice for doing the colouring.

Update

Based on @torek's answer I have come close to replicating git branch -vv output with:

git for-each-ref --format='%(HEAD) %(if)%(HEAD)%(then)%(color:green)%(end)%(align:left,53)%(refname:short)%(end)%(color:reset)%(objectname:short) %(if)%(upstream)%(then)[%(color:blue)%(upstream:short)%(color:reset)%(if)%(upstream:track,nobracket)%(then): %(color:red)%(upstream:track,nobracket)%(color:reset)%(end)] %(end)%(subject)' refs/heads/

It's not perfect though:

I've added this to my gitconfig to use as an alternate.

Update 2

I fixed the colour reset issue. I was sure I'd tried %(color:reset) but after reading the git log help and seeing it has a colour reset mechanism I tried it again and it worked.

Update 3

Using the two pass method from this answer, I've arrived at:

        br = "!f() {  \
               if [ -z \"$1\" ] || [ \"$1\" = \"-v\" ] || [ \"$1\" = \"-vv\" ]; then  \
                   width=$(git for-each-ref --format='%(refname:short)' refs/heads | wc -L);  \
                   if [ \"$1\" = \"-v\" ]; then  \
                       git for-each-ref --format=\"%(HEAD) %(if)%(HEAD)%(then)%(color:green)%(end)%(align:left,$width)%(refname:short)%(end)%(color:reset) %(objectname:short) %(if)%(upstream:track,nobracket)%(then)[%(color:red)%(upstream:track,nobracket)%(color:reset)]%(end) %(subject)\" refs/heads/;  \
                   else  \
                       git for-each-ref --format=\"%(HEAD) %(if)%(HEAD)%(then)%(color:green)%(end)%(align:left,$width)%(refname:short)%(end)%(color:reset) %(objectname:short) %(if)%(upstream)%(then)[%(color:blue)%(upstream:short)%(color:reset)%(if)%(upstream:track,nobracket)%(then): %(color:red)%(upstream:track,nobracket)%(color:reset)%(end)] %(end)%(subject)\" refs/heads/;  \
                   fi;  \
               else  \
                   git branch \"$@\";  \
               fi;  \
               }; f"

This calculates the required alignment width, colours the tracking information in a -v or -vv situation, makes the default no-argument form be -vv instead, and keeps the rest of the branch functionality by passing it through. There's room for improvement in the argument processing, but this is good enough for now.

Upvotes: 1

Views: 556

Answers (1)

torek
torek

Reputation: 488173

git branch does not have a way to change the color of the word gone here.

If your Git is new enough—check your installed documentation for git for-each-ref to see if it supports these fields and %(if) tests—then git for-each-ref does have a way to set the color of the %(upstream:track) output. You can use this to build the same output you would get from git branch -vv, except that it has the color support that you want.

Here is a simple example:

git for-each-ref \
    --format='%(refname:short) '\
'%(if:equals=gone)%(upstream:track,nobracket)%(then)'\
'%(color:red)%(end)%(upstream:track)%(color:black)' \
    refs/heads/

I broke it up into lines for StackOverflow posting purposes. The one line version may be more suitable as a starting point, especially if you are not using sh/bash:

git for-each-ref --format='%(refname:short) %(if:equals=gone)%(upstream:track,nobracket)%(then)%(color:red)%(end)%(upstream:track)%(color:black)' refs/heads/

Note that you will need to augment the set of %-directives to show all of what git branch -v shows.

Upvotes: 2

Related Questions