So, if like me you spend a lot of your time in front of a terminal, you
want it to look good; and who says stylish can’t also be practical?
This guide will focus on themes for Zsh: an extension of the Bourne Shell
(sh) with a multitude of useful features. If you want to know more about Zsh
and how to switch to it, give this article
by How-To Geek a read.
If you've made it this far, I have to assume that you've been convinced by
the various benefits of Zsh and have made it your default shell. "But how do
I make it look cool?" I hear you ask; the answer is themes.
Oh My Zsh
The easiest way of applying a theme to your Zsh shell is to use
Oh My Zsh. Oh My Zsh provides
multiple other ways of customising your Zsh shell, not just themes, however,
these are outside of the scope of this guide.
To install Oh My Zsh, simply run one of the commands below:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
For the security-conscious among you, the following command downloads the
installation script without running it so you can see exactly what it does
before executing it:
curl -Lo install.sh https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
Oh My Zsh comes with several themes pre-installed, which you can read about
here. There are also many custom themes published on GitHub which are often
collated in repositories like the
awesome-zsh-plugins repository. These can be installed by downloading their
.zsh-theme files and placing them
in the Oh My Zsh custom themes directory, which by default is
~/.oh-my-zsh/custom/themes, and
can be enabled by setting the ZSH_THEME variable in your
.zshrc file to the theme's name.
However, if like me you fail to find one that suits your needs, or if you
truly want to make your shell your own, you can write your own theme.
Writing Your Own Zsh Theme
The first step in writing your own Zsh theme is to create a new file with a
.zsh-theme extension in the Oh
My Zsh custom themes directory (e.g.
~/.oh-my-zsh/custom/themes/mycustomtheme.zsh-theme). Once this is done, you'll want to enable the theme by setting the
ZSH_THEME variable in your
.zshrc file (e.g.
ZSH_THEME="mycustomtheme"). Now
you're ready to start writing your theme.
A Simple Prompt
Let's start with a simple prompt. Put the following line into your theme
file and save it:
PROMPT='> '
Now open a new terminal running Zsh. You should see something like
this:
A More Informative Prompt
Now this isn't very exciting, or useful, so let's add some more
information. Various pieces of useful information can be added to Zsh
themes using syntax such as that shown in the table below:
Syntax |
|
Username |
%n |
Hostname |
%m |
Status of Previous Command |
%? |
Path to Current Directory with
~ Substitution
|
${PWD/#$HOME/~} |
12-hour Time |
%t |
24-hour Time |
%T |
24-hour Time with Seconds |
%* |
Date/Time Using a strftime
Format String |
%D{string} |
Change your code to the following and save the file:
PROMPT='[%D{%H:%M:%S}] %n@%m%:${PWD/#$HOME/~} > '
Now switch back to your terminal. You'll notice that your prompt hasn't
changed. This is because you need to tell Zsh to reload the theme. To do
this, you can either open a new Zsh session or run the following
command:
source ~/.zshrc
This tells Zsh to reload the configuration specified in your
.zshrc file, causing it to
reload your theme.
You should now see something like this:
As you can see, the code above tells Zsh to display the current time, your
username, hostname, and current working directory (replacing your home
directory with the
~ character), giving you a
prompt similar to Bash's default.
Adding Colour
At this point, you're probably shouting at your screen "But Bash's
default prompt has colour!". Well let's add some to our prompt shall we?
Zsh themes can use a variety of syntaxes to control colour which I have
summarised in the table below:
Using Colour Codes |
Using String Values |
Using Either String Values or Colour Codes |
Resetting Formatting |
|
Foreground (Text) Colour |
%{$FG[000]%} |
%{$fg[black]%} |
%F{000} %F{black} |
%f |
Background Colour |
%{$BG[000]%} |
%{$bg[black]%} |
%K{000} %K{black} |
%k |
All Formatting |
%{$reset_color%} |
Zsh accepts the following string values for defining colour:
- black
- blue
- cyan
- green
- magenta
- red
- white
- yellow
To view accepted colour codes, run the following command:
spectrum_ls
This will produce a list of supported colours and their respective codes
in the format shown below:
Change your code to the following:
PROMPT='%{$FG[007]%}[%D{%H:%M:%S}] %{$FG[014]%}%n@%m%{$FG[015]%}:%{$FG[007]%}${PWD/#$HOME/~}%{$FG[015]%} > %{$reset_color%}'
Now reload your theme and you should see something like this:
Choosing the right colour scheme for you can take some trial and error,
however, reloading your theme after every change to see how it looks can
be tedious. To avoid this, you can use the
print -P command to see what
your prompt will look like as shown below:

Once you've found a colour scheme that you like, simply set the
PROMPT variable in your theme
file accordingly and reload your theme.
Adding Formatting
Zsh also allows you to format your text. As with colour, you can use a
variety of sytaxes to add formatting to your prompt which I have again
summarised in a table below:
Applying Formatting |
Resetting Formatting |
|
Bold |
%{$FX[bold]%} %B %{$fg_bold[black]%} |
%{$FX[no-bold]%}
%b |
Italic |
%{$FX[italic]%} |
%{$FX[no-italic]%}
|
Underline |
%{$FX[underline]%} %U |
%{$FX[no-underline]%} %u |
Standout | %S | %s |
Blink |
%{$FX[blink]%} | %{$FX[no-blink]%} |
All Formatting |
%{$reset_color%} |
Change your code to the following:
PROMPT='%{$FG[007]%}[%D{%H:%M:%S}] %{$FX[bold]$FG[014]%}%n@%m%{$FX[no-bold]$FG[015]%}:%{$FX[italic]$FG[007]%}${PWD/#$HOME/~}%{$FX[no-italic]$FG[015]%} > %{$reset_color%}'
When you reload your theme, you should see something like this:
Note: As with colours, the
prompt -P command can be used
to test out your formatting without having to reload your theme.
Adding Logic
So a useful feature of
.zsh-theme files is that
they are basically just shell scripts, which means you can add logic to
them. For example, as a pentester, I often find myself switching between
my user account and the root account on my machine. Now as our theme
stands in its current form, I'd have to read the prompt to see which
user I'm currently using, but what if I could easily tell with just a
glance? Change your code to the following:
local user_colour='014'; [ $UID -eq 0 ] && user_colour='027'
PROMPT='%{$FG[007]%}[%D{%H:%M:%S}] %{$FX[bold]$FG[$user_colour]%}%n@%m%{$FX[no-bold]$FG[015]%}:%{$FX[italic]$FG[007]%}${PWD/#$HOME/~}%{$FX[no-italic]$FG[015]%} > %{$reset_color%}'
You'll notice that at first, this doesn't appear to have changed
anything, however, run Zsh as the root user and you should see something
like this:
As you can see, the theme now changes the colour of the username and
hostname if you're logged in as the root user, making it obvious which
user you are currently using at a quick glance.
Note: In order for the sudo su command to have the effect shown in the example, Zsh must be set as the default shell for the root account and your theme must be specified in root's .zshrc file.
Updating Your Prompt in Real-Time
You may have noticed that up until now, your prompt is not updated once
it has been generated. This can be inconvenient if you're using features
like timestamps as your prompt will indicate their status at the time of
generation and not at the current time. To combat this problem, you can
tell Zsh to regenerate your prompt at regular intervals. To do this, add
the following code to your
.zsh-theme file:
TMOUT=1
TRAPALRM() {
zle reset-prompt
}
This will tell Zsh to regenerate your prompt every second, keeping
features like your timestamp accurate.
Note: This won't cause you to lose any text you have already typed into your
terminal, so you don't have to worry about having to type your commands
insanely fast!
Incorporating Git Information
A popular feature of Zsh themes is their ability to display Git
information. This can be achieved by integrating some pre-defined
functions and variables into your theme. Zsh has the following pre-defined
functions available to display git information:
git_prompt_status
git_prompt_info
The following pre-defined variables can be used to modify what these
functions return:
ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX
ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX
ZSH_THEME_GIT_PROMPT_ADDED
ZSH_THEME_GIT_PROMPT_AHEAD
ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE
ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR
ZSH_THEME_GIT_PROMPT_BEHIND
ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE
ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR
ZSH_THEME_GIT_PROMPT_CLEAN
ZSH_THEME_GIT_PROMPT_DELETED
ZSH_THEME_GIT_PROMPT_DIRTY
ZSH_THEME_GIT_PROMPT_DIVERGED
ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE
ZSH_THEME_GIT_PROMPT_MODIFIED
ZSH_THEME_GIT_PROMPT_PREFIX
ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS
ZSH_THEME_GIT_PROMPT_REMOTE_MISSING
ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED
ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX
ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX
ZSH_THEME_GIT_PROMPT_RENAMED
ZSH_THEME_GIT_PROMPT_SHA_AFTER
ZSH_THEME_GIT_PROMPT_SHA_BEFORE
ZSH_THEME_GIT_PROMPT_STAGED
ZSH_THEME_GIT_PROMPT_STASHED
ZSH_THEME_GIT_PROMPT_SUFFIX
ZSH_THEME_GIT_PROMPT_UNMERGED
ZSH_THEME_GIT_PROMPT_UNSTAGED
ZSH_THEME_GIT_PROMPT_UNTRACKED
The best way to understand what these do is to look at their use in existing themes and to play around with them. When used effectively, these functions and variables can modify your
prompt to display various Git information when your current working
directory lies within a Git repository. For example, you may see something
like this:
This example shows the current branch and the various statuses of the
files within a Git repository.
It should be noted that in this example, the Git information appears on
the right-hand side of the terminal. This was achieved by using the
RPROMPT variable, which works
in the same way as the
PROMPT variable, however, it is
displayed on the right-hand side of the terminal.
Conclusion
This guide is not the be-all and end-all of Zsh theme knowledge, however,
it should be more than enough to get you started in the wonderful world of
Zsh themes.
If you like the theme used in the examples, you can download the full
version from my GitHub
here.
Happy theming!
No comments:
Post a Comment