How to accomplish a “responsive” bash prompt
I have always liked having my full path in my bash prompt, and also (when applicable) my current git branch. This way I always have the proper context I need to be able to navigate quickly and prevent myself from having to constantly type pwd to figure out where I am.
This works well until you’re working in a smaller terminal window and are deep within a project. For one reason or another you’re down to 80-100 columns, and your prompt is taking up the entire width of the terminal (and then some).
I also have attempted to use the 2 line prompt where the info is on the first line, leaving your commands to be entered on the next line, but I find this really annoying. If you’re in the same boat as me, let me save you the hours of work on something so trivial.
The responsive prompt in action
I have my prompt set up to switch at 110 columns to a more concise layout. At more than 110 columns, it looks like this.

When I go below the terminal width of 110 columns I wanted to streamline it, while still providing relevant info that will help me get 90% of the information I get from the full prompt. This is what I ended up with.

Currently it checks the terminal width every time a new prompt is rendered, so reloading your bash environment is not necessary.
Extra
Another neat thing I recently did with my prompt is change the color of the arrow to red if the previous command returns an exit status other than zero.

The Code
If you’re new to bash prompt customization, please at least skim through this before continuing. It provides the basics of prompt customization, this is a more advanced customization.
First I reconstructed the \w prompt variable that produces the current working directory (with the ~ home directory replacement), with this function.
working_directory() {
dir=`pwd`
in_home=0
if [[ `pwd` =~ ^$HOME($|\/) ]]; then
dir="~${dir#$HOME}"
in_home=1
fi
if [[ `tput cols` -lt 110 ]]; then # <-- Checking the term width
first="/`echo $dir | cut -d / -f 2`"
letter=${first:0:2}
if [[ $in_home == 1 ]]; then
letter="~$letter"
fi
proj=`echo $dir | cut -d / -f 3`
beginning="$letter/$proj"
end=`echo "$dir" | rev | cut -d / -f1 | rev`
if [[ $proj == "" ]]; then
echo $dir
elif [[ $proj == "~" ]]; then
echo $dir
elif [[ $dir =~ "$first/$proj"$ ]]; then
echo $beginning
elif [[ $dir =~ "$first/$proj/$end"$ ]]; then
echo "$beginning/$end"
else
echo "$beginning/…/$end"
fi
else
echo $dir
fi
}
Then to abbreviate the git branch I wrote this function…
parse_git_branch() {
if [[ -f /usr/local/etc/bash_completion.d/git-completion.bash ]]; then
branch=`__git_ps1 "%s"`
else
ref=$(git-symbolic-ref HEAD 2> /dev/null) || return
branch="${ref#refs/heads/}"
fi
if [[ `tput cols` -lt 110 ]]; then # <---- Again checking the term width
branch=`echo $branch | sed s/feature/f/1`
branch=`echo $branch | sed s/hotfix/h/1`
branch=`echo $branch | sed s/release/\r/1`
branch=`echo $branch | sed s/master/mstr/1`
branch=`echo $branch | sed s/develop/dev/1`
fi
if [[ $branch != "" ]]; then
echo "$branch "
fi
}
Then we wrap it all up into a prompt function that I assign to PROMPT_COMMAND which gets executed before every time the prompt is rendered. This is where the exit status checking happens.
prompt() {
if [[ $? -eq 0 ]]; then
exit_status='\[\e[0;34m\]› \[\e[00m\]'
else
exit_status='\[\e[0;31m\]› \[\e[00m\]'
fi
prompt='\[\e[0;33m\]$(working_directory)\[\e[00m\]\[\e[0;32m\] $(parse_git_branch)\[\e[00m\]'
PS1=$prompt$exit_status
}
PROMPT_COMMAND=prompt
And vioala, your prompt is now smart enough to be more conservative with smaller terminal widths.
Awesome!! -> How to accomplish a “responsive” bash prompt http://t.co/RtcRriYB
[...] How to accomplish a “responsive” bash prompt → 43 seconds ago [...]
How to accomplish a “responsive” bash prompt http://t.co/lMZ9CeTv #wordpress
How to accomplish a “responsive” bash prompt http://t.co/UpCAyLhB
Found this through Alex King’s post. I really like this prompt. I just set it up on my dev system.
This is a great way to deal with working on different screen sizes; it makes using iSSH on an iPhone (in a pinch) easier.
I put the code in a gist so I can pull it into my own config files, if anyone else is interested it’s posted here: https://gist.github.com/4237983