Quest for a Nicer Prompt

| Comments

Fancy console prompts are fun, but its a tradeoff. The problem is, once you put all this extra info in there it gets too long.


The prompt should not get in the way. It should show as few characters as possible but be highly helpful, informative, and pleasant.

Home Sweet Home

the simplest prompt

Logged in as myself, on my local machine, in my home directory. It just reads at home - three characters and a cursor.

Once I’ve logged into a remote box as a different user, and switched away from my home directory, the same PS1 shows a more conventional prompt:

anatomy of the prompt

The path is underlined not just because it looks nice. Command-clicking on pathnames opens a Finder window in iTerm2, and I think that it looks more like a clickable link in this way.

A Shorter Path

Back to how I find it annoying when the path gets too long and commands start wrapping lines as I type. 40 chars is about the maximum to show for a path. There are two strategies to shorten paths:

1. First-class Website Roots

As a web developer I spend most of my time inside of a web project root folders. Locally, that’s ~/Sites/ but on remote servers it’s usually /var/www/vhosts/ For these cases, the path is reduced to a web-like scheme prefix (//):

web projects

2. Ellipsis in the Middle

Long paths are truncated using two methods:

  • Split the path on the slashes, show the first three parts and the last two, join with “…”
  • Use the first 25 characters of the path and the last 15, join with “…”
  • display whichever version ends up being shorter

The result is that paths are split up more naturally. Really long directory names end up being chopped, wheres shorter paths make it through ok. Its a good balance, and you can still figure out where you are.

truncate long paths

A ruby one-liner does this:

d=ENV["PWD"].gsub(%r{^#{ENV["HOME"]}},"~").gsub(%r{^~/Sites/},"//").gsub(%r{^/var/www/vhosts/},"//");p1=d[0,25]+"…"+d[-15,15].to_s;a=d.split("/");p2=a.first(4)+["…"]+a.last(2);p2=p2.join("/");puts(d.size>[p1.size,p2.size].min)?((p1.size< p2.size)?p1:p2):d

Git Branch and Status

Finally, the git branch is displayed in brackets, for any directory under git control. If there are any uncommitted changes, a red asterisk is also helpfully displayed. It would be nice to have the branch name be truncated as well (they too can get longish), and maybe showing ahead/behind status. But that’s not there yet.

shows current git branch and status

Other Stuff

  • sets the title bar for the terminal window (without the colors or git branch info)
  • The root user is always shown in red
  • hosts on local subnets (192.*, 10.*) are shown in green
  • many other colors and effects are defined for tweaking

What’s your PS1?

I’ve been slowly customizing my PS1 bash prompt over the last few years to try and get something really pretty and usable working. So this is what I’m currently satisfied with, a fairly involved collection of bash functions, mixed with some inline ruby code. Looks chaotic, but it should pretty easy to customize.

The script:

To get it set up, save the source locally:

curl -o ~/.ps1

Then edit your .bashrc (or .bash_profile) add these lines:

DEFAULT_USERNAME=jeremy    # change this to yours!
SERVERNAME=ninja           # only if you want to override the default hostname
source ~/.ps1

Now do this for all your shell accounts. Or hey, make a dotfiles repository and use that. Or use Puppet or something else!

thanks to Ivan Jovanovic for sharing the git branch and bash functions approach with me, and to the dotfiles of Ryan Bates and Mathias Bynens for further inspirations

* I prefer Liberation Mono font for programming.