Prompt styling in zsh

Revealed by sykora within linux on July 27th, 2008

Your prompt is the centerpiece of your command-line experience. No other piece of text is printed on the screen as much as your prompt is, so you might as well make it worth its while.

Here are some of the things you can do with your prompt, so that it both looks aesthetically pleasing (as far as one can go with 8 bit color) and so that it’s actually useful.

My shell of choice is zsh, the Z-Shell. Compared to other shells, like bash, ksh, csh, etc, zsh is newer, and has incorporated many of their best features. You can do with zsh, anything you can do in another shell, so there’s no excuse for not switching. zsh is possibly the most feature packed shell in existence, and allows you to customize almost everything. I will be focussing on prompt styling in zsh, which in most cases is common to all shells, but not in some.

Types of Prompts

In general, there are 6 different prompts, used at different times :

  1. PS1 (or PROMPT1 or just PROMPT) : The main prompt. It’s printed before each command is read.
  2. PS2 (or PROMPT2) : The secondary prompt, used when the shell asks for more information to complete a command, such as if, while, etc.
  3. PS3 (or PROMPT3) : A prompt used inside a select loop.
  4. PS4 (or PROMPT4) : Debugging trace prompt.
  5. RPS1 (or RPROMPT1) : Displayed on the right hand of side of the screen, while PS1 is being shown on the left
  6. RPS2 (or RPROMPT2) : Displayed on the right of the screen, while PS2 is shown on the left.
  7. SPROMPT : Prompt used for spelling corrections.

That may seem like a lot, and it is. Of these, most of you will only have to configure PS1 and PS2. I’ve also configured PS3 and PS4 for use while I’m programming in the shell, but these are pretty simple. RPROMPT seemed like a good idea once upon a time, and I used it to display the date and time, but that was scrapped as soon as I made multiline prompts, as they took up too much space on the right.

Prompts in zsh : The easy way.

zsh comes with a number of prompt themes prewritten. They can be activated like so:

$> autoload promptinit && promptinit
$> prompt <prompt name>

The available prompts can be listed by prompt -l,

$> prompt -l
Currently available prompt themes:
adam1 adam2 bart bigfade clint elite2 elite fade fire off oliver redhat suse walters zefram</pre>

You can get a preview of available themes with prompt -p, and set the prompt permanently with prompt -s.

That wasn’t hard was it? While this method is simple, it doesn’t let you customize exactly what’s displayed, where it goes and the colors used.

If you want more control over your prompt, read on.

Prompts in zsh - The hard way

It’s not that hard, not really. You’ll just need to learn a truckload of expansion sequences. Thankfully, zsh simplified color escapes to a moderately sane extent (^[\m01;34; anyone?).

Prompts are created by using prompt expansion sequences, which consist of a '%' character, followed by a single character, like C's scanf/printf format flags.

There are a large number of prompt escape sequences, far too many to list here. The most common ones are %~, for the current directory with ~ relative paths, %# for a privilege indicator, and %!, the history number. The full list can be found at the bottom of the zshmisc manpage.

Setting up the prompt

Setting up the prompt is as easy as filling a shell variable with the prompt string you want. I strongly suggest that you use "$> print -P" to try out your prompts before actually switching to them.

For example, if you wanted a prompt that displayed your username, hostname and the name of the current directory, you would use something like ;

$> PROMPT="%n@%m %~> "
sykora@localhost ~>

The rest is just learning what escape sequences you want, and putting them in.

Adding Color

In the old days, you'd have to insert ANSI color escape sequences to get color in your terminal. For those who aren't in the know, ANSI sequences are really messy character strings consisting of weird key-combos and numbers. Really ugly stuff. Now...you still have to insert ANSI color escape sequences...but you don't have to do it yourself - you let zsh do it for you.

$> autoload colors
$> colors

That sets up a number of associative arrays, or dictionaries, with the color codes you need. For example, to turn your text into cyan, use $fg[cyan]. To make that bold, use $fg_bold[cyan] instead. If you want to return all colors to their defaults, use $reset_color.

Inside prompts, you’ll have to put colors within a “%{…%}” string to get them to work properly. Since I use only a few colors, i do this before hand with variables like so :

$> local text_color="%{$fg_no_bold[cyan]%}"
$> local text_emph="%{$fg_bold[cyan]%}"
$> .. other colors

In this way, you can put ${text_color} inside your prompt, and it should work perfectly.

That’s all there is to prompt theming. For those who’re interested, here’s mine. It’s based on the elite2 prompt which is included with zsh, but rewritten with a few changes.

autoload -Uz colors && colors
local text="%{$fg_no_bold[cyan]%}"
local text_emph="%{$fg_bold[cyan]%}"
local punctuation="%{$fg_bold[grey]%}"
local emph="%{$fg_bold[white]%}"
local final="%{$reset_color%}"
 
PROMPT="${punctuation}(${text_emph}%n${emph}@${text}%m${punctuation})(${emph}%j${text} job[s]${punctuation})(${text}%D{%A, %B %d, %Y : %H:%M:%S}${punctuation})-
(${emph}%#${punctuation}:%!${text}:%1~${punctuation})-${final} "

 
PROMPT2="${text}%_${punctuation}|-${final} "

Tags: , , ,

Leave a Reply

Powered by Wordpress, valid XHTML and CSS. Original theme by Themelab, modifications by me.
Gatekeeper