zerowidth positive lookahead

Command Prompt Tips

Spend a lot of time at the command line? Here’s a few things to try out.

Unicode!

Thanks to a tweet from Geoffrey Grosenbach, I learned that Terminal.app can have unicode in the command prompt.

Here’s my basic prompt, which uses “HEAVY ROUND-TIPPED RIGHTWARDS ARROW”:

~ ➔

Current git branch

Since I use git for revision control, it’s helpful to know which branch I’m working on.

~/code/tire_swing (master) ➔

The simplest way to achieve this in bash is to use the git-completion.bash script. Along with bash completion for the git command, it defines the __git_ps1 function. When you’re in a git project, it’ll show the current branch, and doesn’t display anything otherwise.

To install git’s bash completion via macports, make sure you have bash-completion and the git variant with the bash-completion script installed:

~ ➔ sudo port install bash-completion
~ ➔ sudo port install git-core +bash_completion

And add this code to your .profile:

if [ -f /opt/local/etc/bash_completion ]; then
  . /opt/local/etc/bash_completion
fi

Add or change this in your .profile:

# note the single quotes! these are required, unless you sidestep the whole
# "when does it get interpolated" issue by using PROMPT_COMMAND, as shown later on
export PS1='\w$(__git_ps1) ➔ '

You can call __git_ps1 with a format argument as well (uses printf):

# single quotes...
export PS1='\w$(__git_ps1(' ~%s~')) ➔ '

An alternative way of getting the current branch, from Geoffrey Grossenbach. For more things to try, including zsh-compatible settings, see this post.

parse_git_branch() {
  git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}

# single quotes...
export PS1='\w$(parse_git_branch) ➔ '

Git dirty flag

Along with the current branch, I also want to know when there are uncommited changes in my working copy. I use a lightning bolt, “HIGH VOLTAGE SIGN”:

~/code/tire_swing (master) ➔ touch somefile
~/code/tire_swing (master)⚡ ➔

Based on code and comments from Kevin Barnes:

git_dirty_flag() {
  git status 2> /dev/null | grep -c : | awk '{if ($1 > 0) print "⚡"}'
}

# single quotes...
PS1='\w$(__git_ps1)$(git_dirty_flag) ➔ '

Exit status

This one thanks to Tim Pease. This lets me know when something failed:

~ :) ➔ ls /nonexistent
ls: /nonexistent: No such file or directory
~ :( ➔
# using double quotes when specifying PS1 now. PROMPT_COMMAND is executed
# every time a new prompt is shown.
prompt_func()
{
  previous_return_value=$?;
  prompt="\w$(__git_ps1)$(git_dirty_flag) "
  if test $previous_return_value -eq 0
  then
    PS1="${prompt} :) ➔ "
  else
    PS1="${prompt} :( ➔ "
  fi
}
PROMPT_COMMAND=prompt_func

All together now

In the examples above, I left out color. Here it is with everything:

Example of full-color prompt

And the code:

COLOR_YELLOW="\[\e[33;40m\]"
COLOR_RED="\[\e[31;40m\]"
COLOR_GREEN="\[\e[32;40m\]"
COLOR_NONE="\[\e[0m\]"

git_dirty_flag() {
  git status 2> /dev/null | grep -c : | awk '{if ($1 > 0) print "⚡"}'
}

prompt_func()
{
    previous_return_value=$?;
    prompt="${COLOR_GREEN}\w${COLOR_NONE}$(__git_ps1)${COLOR_YELLOW}$(git_dirty_flag)${COLOR_NONE} "
    if test $previous_return_value -eq 0
    then
        PS1="${prompt}➔ "
    else
        PS1="${prompt}${COLOR_RED}➔${COLOR_NONE} "
    fi
}
PROMPT_COMMAND=prompt_func

For those of you using ZSH, take a look at this pastie.