So I recently picked up a shiny new MacBook. This was not my first time around this particular wheel. I’ve enjoyed them for professional and personal use for many years.

This time I thought I’d try a rather tidier approach to shell setup and started with a blank slate and — inspired by a Jess Frazelle talk I enjoyed at Kiwicon some years ago — a goal of running a lot more software in Docker containers to isolate it at least a little bit from my $HOME and precious/private data.

This post is about the shell bits. There are probably millions of posts like it, but this one is mine. ;-)

You can find my scratchings on the Docker angle here.

Colourful text, tidily

A simple shell function is a good helper for adding colour to things. If Google searches are any indication, people typically use a set of shell variables for this. I prefer a function as it stops all the colours leaking out into the shell variable namespace. Invoking the shell function does not result in any child processes (I verified this!) and is quite fast.

_colour() {
	case "$1" in
		none)          printf  "\e[0m"     ;;
		white)         printf  "\e[1;37m"  ;;
		...
		light_gray)    printf  "\e[0;37m"  ;;
	esac
}

Bash prompt, colourfully

I like a nice simple shell prompt, but with a timestamp in it. The \[...\] sections help bash not get confused about how long the text is. They belong around any part of the prompt that will be effectively zero-width — ie. all the colour-change escape sequences. Otherwise you can be typing away at the shell prompt and suddenly the cursor will wrap around to the start of the line. Confusing. Again, this is all wrapped up in a function to help prevent things leaking out into shell variables.

_set_prompt() {
	local chostname=$(_colour cyan)
	local ccwd=$(_colour brown)
	local csep=$(_colour light_gray)
	local cbr=$(_colour green)
	local cdol=$(_colour white)
	local cnone=$(_colour none)
	PS1="\[${cdol}\]\A \[${cbr}\]<\[${chostname}\]\h\[${csep}\]:\[${ccwd}\]\w\[${cbr}\]> \[${cdol}\]\$\[${cnone}\] "
	PS2="\[${cdol}\]> \[${cnone}\]"
}

putting it all together

This is my complete $HOME/.bash_profile:

export PATH="$HOME/shell/wrappers:$PATH"
if [ -n "$PS1" ] ; then
	source "$HOME/.bashrc"
fi

And the almost-as-short $HOME/.bashrc:

source "$HOME/shell/aliases.sh"
source "$HOME/shell/colours.sh"
source "$HOME/shell/prompt.sh"
_set_prompt

That’s it! I’m not missing any of the gunk I used to carry around, and I also don’t need the ridiculous cacheexec hack that I used to use to try to make my complicated prompt actually acceptably fast.