solovyov.net

Useful shell prompt#

3 min read · shell

There are only a few apps I use every day and shell — ZSH — is one of the most used. It’s been that way since the beginning of the ’00s and back then I spent a lot of time configuring my prompt to be a good balance between compact/readable and useful. I found that I dislike fancy two-line prompts, information on a right-hand side (because of its awkward behavior), and stuff like that. So the result looks like that:

piranha@rigel ~> █

where is a cursor. It shows username, @ to separate it from hostname - or # if this is uid 0 shell, then hostname, and a home-abbreviated path. One of the fancy things is that space before the cursor is Unicode glyph \u00A0 - non-breaking space - which is bound in ZLE to delete everything to the beginning of a line. Unfortunately, this does not work with Terminal.app, so it just sits there waiting for a better time. This setup along with colors had no changes for over a decade.

But a week ago a saw a tweet with an idea to change prompt’s prompt (the > thingie) to a red color when previous command exited with an error status. This motivated me to cleanup and update my prompt to a newer conventions. This is a result:

prompt screenshot

You can see I removed my username since it really gives me no information, no reason to spend space on that. I also really like white background, but if you don’t, changing colors is easy — I’ll explain how everything works.

Let’s break down it bit by bit. The prompt syntax is a little hard on the eyes - in case if you have ideas on how to write this so next time I won’t have to dig deep into ZSH documentation, I’ll be glad to listen.

p_at='%(!.%F{red}%B#%b%f.@)'

In this case, few things are interesting:

p_host='%F{blue}%m%f'
p_path='%F{blue}%~%f'

Those are easy to understand, just refer to documentation%m is a hostname before the first dot, %~ is a path where $HOME is abbreviated to ~.

p_pr='%(?.%F{blue}.%F{red})>%f'

This is a new part. ? means “True if exit status of the last command was 0”. So if a command exited nicely (with a status code 0), then it’s going to be blue >, in other case it’s going to be red >. Voila! :-)

End result looks like this:

p_at='%(!.%F{red}%B#%b%f.@)'
p_host='%F{blue}%m%f'
p_path='%F{blue}%~%f'
p_pr='%(?.%F{blue}.%F{red})>%f'

PS1="$p_at$p_host $p_path$p_pr "
unset p_at p_host p_path p_pr

You can see I’m unsetting color in every variable and unset those variables — cleaning up after yourself is a valuable habit, especially with a shell. :-)

I’m pretty sure the same could be done for bash (or tclsh, or whatever), but I’m not using it so… If anybody wants to contribute a similar configuration for other shells, I’ll gladly link to a post or add it here.


See also
API pagination design
ElasticSearch query builder
Higher-order functions are like inheritance
A tale of webpage speed, or throwing away React