Dynamic prompt with Git and ANSI colors

I recently tinkered (again) to put my current Git working branch in my prompt. It resulted in very useful addition to the tool I use a lot in my everyday work.

However it turned out my implementation had a bug. When my prompt plus command got near the window border it wrapped the text. It should wrap but in my case it did so too early and not on a new line but with the overflowing text replacing the beginning of my prompt.

I have had this problem in the past when tinkering with my prompt. This time around I was not going to throw in the towel however and so I went to read up on terminals.

The problem, I found out, was that I was not enclosing my non-printing characters. When I changed my code accordingly it handled the wrapping perfectly.

c_reset='\[\e[0m\]'
c_user='\[\033[1;33m\]'
c_path='\[\e[0;33m\]'
c_git_clean='\[\e[0;36m\]'
c_git_dirty='\[\e[0;35m\]'
 
PS1="${c_user}\u${c_reset}@${c_user}\h${c_reset}:${c_path}\w${c_reset}$(git_prompt)\$ "

Relieved having conquered this tiny area of Bash I got back to work. Then when next I committed my code and was expecting the dirty branch color to switch to the clean branch color, it did not. I fired up a new terminal and lo and behold – it had the correct color for my branch.

Some experimenting later it became apparent that I could either use double quotes ("like this") to have my string parsed and the ANSI colors properly applied, or I could use single quotes ('like this') to have the branch value updated dynamically.

A dive in the bash manual (RTFM, right?) showed me a solution to the problem.

PROMPT_COMMAND
    If set, the value is executed as a command prior to issuing each primary prompt.

Instead of setting PS1 directly, I set up PROMPT_COMMAND to have it set PS1 in turn. Then I could both have the colors from double quotes parsing and the dynamic value from calling my function on each new prompt.

The final result?

# Configure colors, if available.
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    c_reset='\[\e[0m\]'
    c_user='\[\033[1;33m\]'
    c_path='\[\e[0;33m\]'
    c_git_clean='\[\e[0;36m\]'
    c_git_dirty='\[\e[0;35m\]'
else
    c_reset=
    c_user=
    c_path=
    c_git_clean=
    c_git_dirty=
fi
 
# Function to assemble the Git part of our prompt.
git_prompt ()
{
    if ! git rev-parse --git-dir > /dev/null 2>&1; then
        return 0
    fi
 
    git_branch=$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')
 
    if git diff --quiet 2>/dev/null >&2; then
        git_color="$c_git_clean"
    else
        git_color="$c_git_dirty"
    fi
 
    echo " [$git_color$git_branch${c_reset}]"
}
 
# Thy holy prompt.
PROMPT_COMMAND='PS1="${c_user}\u${c_reset}@${c_user}\h${c_reset}:${c_path}\w${c_reset}$(git_prompt)\$ "'

The one thing I would like to change now is how I am detecting ANSI color support. Since tput went out the window, I am not sure that is a proper indicator anymore. Hoping to remedy this, I have put a Gist for the prompt up at GitHub. Feel free to fork and improve!