My ZSH prompt setup

February 20, 2008

linux

I like tweak my prompt and I use zsh, thus I have infinite possibilities :-)

I owe much the phil’s prompt which gave me a lot of ideas.

My prompt is ofcourse in full color, as I’m a fan of that too. (Old UNIX users may shrudder at this point…)

Right now I have a prompt that keeps out of my face, but when needed has some usefull extras; like showing background jobs and showing the exit code of the previous command if it wasn’t equal to zero.

Furher more the right side prompt show the current directory.

path

My default prompt looks something like this:

host.user%              pwd

Or in a specific incarnation:

elektron.miekg%             ~

If the path gets too long, only the last part is shown.

The code to fix this:

mypath="%~"
((MAXMID=$COLUMNS / 2)) # truncate to this value
RPS1="$RPSL%$MAXMID<...<$mypath$RPSR"

Line1: put the current path in a variable, as I’m also using colors this was more easy. The next line calculates the half of my terminal width, so the third line will correctly chop the path if it gets too long.

background jobs

A list of background jobs is placed at the left side, but only when there are any. One background job:

[1+] host.user%             ~

Or multiple

[1+,2,3-] host.user%                ~

The code for the jobs-string looks like this:

for a (${(k)jobstates})
{j=$jobstates[$a];i="${${(@s,:,)j}[2]}"
myjobs+=($a${i//[^+-]/})}
myjobs=${(j:,:)myjobs}

The first three lines are the for-loop, where from the $jobstates a new array is created. The last line transforms this array back into a string with ,s in between.

exit code of previous command

Sometimes its very handy to see the exit code of your command, esp. when its not zero (0). You can use echo $? after each interesting command. The code I have in the prompt will only show the exit code if it wasn’t equal to zero at the right side, like so:

host.user%                  ~ (1)

This is relative easy to do in zsh:

RPSR='%(0?..(%?%))'

I’m using a conditional here, if the exit-code is zero do nothing, otherwise print it using ( and ).

full configuration

The full setup if ofcourse somewhat more complicated, so I will just list the files here, have fun with it.

My color definition (~/.zcolors):

###
# See if we can use colors.

autoload colors zsh/terminfo
if [[ "$terminfo[colors]" -ge 8 ]]; then
    colors
fi
for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GREY; do
    eval C_$color='%{$terminfo[bold]$fg[${(L)color}]%}'
    eval C_L_$color='%{$fg[${(L)color}]%}'
done
C_OFF="%{$terminfo[sgr0]%}"

My prompt definition (~/.zprompt):

# load prompt functions
setopt promptsubst
unsetopt transient_rprompt # leave the pwd 

# get the colors
source ~/.zcolors

# set the prompt
set_prompt() {
    mypath="$C_OFF$C_L_GREEN%~"
    myjobs=()
    for a (${(k)jobstates})
    {j=$jobstates[$a];i="${${(@s,:,)j}[2]}"
    myjobs+=($a${i//[^+-]/})}
    myjobs=${(j:,:)myjobs}
    ((MAXMID=$COLUMNS / 2)) # truncate to this value
    RPS1="$RPSL$C_L_GREEN%$MAXMID<...<$mypath$RPSR"
   rehash
}

# print optional number of bg jobs (when 0 show nothing)
# when the path is too long only the last section is shown
# root is simple and all red

# reset the colors when printing the rside prompt always
if [ "$USER" = "root" ]; then
    PS1=$'$C_RED%~ %#% $C_OFF '
else
    PS1=$'$C_L_BLUE%(1j.[$myjobs]% $C_OFF .$C_OFF)%m.%B%n%b$C_OFF$C_L_GREEN%#$C_OFF '
fi
RPSL=$'$C_OFF'
RPSR=$'$C_OFF$C_L_RED%(0?.$C_L_GREEN. (%?%))$C_OFF'
RPS2='%^'

precmd () {
   set_prompt
}
None