Customizing the zsh Prompt with oh-my-zsh Themes

There are a lot of ready made themes for oh-my-zsh users. You can even get a screenshot of each of the themes from a shared dropbox folder. So why would you ever need to know how to make your own theme?

Well, the thing is. When you - like me - end up working in your terminal most of your days, other peoples settings are just not one hundred percent how you want them. Most of the themes are ok, pretty, and useful. But I never found a theme that was really what I needed.

  • I wanted two lines

  • I wanted to know the current path

  • I wanted to know my current username

  • I wanted to know my current host

  • I wanted to know which version of ruby I ran

  • I wanted to know if I was in a git repo

  • I wanted to know if the repo was clean

  • I wanted to know when the last commit was

  • I wanted to know the current branch name

Thats a lot to ask.

Username, hostname and path

The easiest parts are the parts that are in environment variables in zsh. The current path, the home folder, the current username and the current hostname are all built-ins in zsh.

My prompt looks like this at the time of writing:

My prompt

The prompt string for showing the left side of this, is as follows

<code class="language-bash">
PROMPT='
%{$fg[cyan]%}[%~% ]
%{$fg[magenta]%}%n%{$reset_color%} at %{$fg[yellow]%}%m%{$reset_color%} %B$%b '
</code>

And no-one will understand that without some help. It is utter gibberish. There is however a list of built-ins. And with the help of that, and knowing a bit about the color coding that happens here as well, it can be deciphered.

The path

The path part is the easiest to understand. The %~ is showing the current working directory, but replacing $HOME from $PWD so that everything under your home path is shown as a tilde followed by the subpaths (instead of the absolute path to your home path first).

The username and hostname

This is only relevant if you use your theme on multiple machines. All the servers I have access to at work, has a clone of my dotfiles, and thus of my theme. In this case it is very nice to know wether you are root or your normal user, and wether you are on your local machine, or on some important storage server with a couple of terabyte important data.

The username part is: %n and the hostname is shown up until the first dot (instead of the FQDN), this is done with: %m - both are wrapped in some color codes, but that is really all there is to it.

The right side

There are several ways to show a right side prompt in zsh. I have opted for the simplest to understand. A environment variable called RPROMPT. It works exactly like PROMPT, except it is shown on the right side of the screen.

<code class="language-bash">
RPROMPT='$(git_time_since_commit)|$(git_custom_status)%{$fg[white]%}[`~/.rvm/bin/rvm-prompt`][node `node -v`]%{$reset_color%} $EPS1'
</code>

In my actual theme the RPROMPT is wrapped in some if statements, to ensure that parts of it is only written, if the command is present. The prompt uses some function calls from the theme script called git_time_since_commit, and git_custom_status - both of which exists in several themes for oh-my-zsh.

git_time_since_commit shows the time since last commit in the prettiest format (just like the old times_ago_in_words in known from rails). Last but not least, the time since last commit is colorencoded from green over yellow to red, depending on how long ago the last commit was - but only if the repo is “dirty”.

git_custom_status shows the current branch, and wether the current branch is clean, with a red asterisk, if is not.

Ruby version and node version

Since I run rvm, and have multiple projects running very different versions of ruby (everything from MRI 1.8.7 to 2.0.x and both Rubinius and Jruby) I like to know what version I am running currently. This mostly important on my local machine.

Furthermore we run node on a lot of our production servers, and we have a lot of different versions installed (and I run the latest locally). I find it usefull to know at all times what version of node is running on the current machine. (However I sometimes hate the extra calls to rvm and node, which sometimes seems to lag a bit, and the prompt will load slower)

both the ruby version and the node version is printed through subshells

<code class="language-bash">
`~/.rvm/bin/rvm-prompt`
</code>

and

<code class="language-bash">
`node -v`
</code>

You can see my complete theme as part of my dotfiles. Direct link.

Or as an embedded gist: