 davelab
 GitHub

Configuring Your Prompt

Overview

The icon characters used in some of the example format-strings require you to install a specific font and configure your terminal emulator to use it. See Nerd Fonts for details.

You can view the different available fonts here.

And you can search for specific icons here.

I like the monospace Hack font, personally.

If you do not want to install a new font, you can either omit the lines with broken fonts, or you can replace them with ASCII characters or unicode glyphs supported by your current font.

If you are on Mac, you should be able to install these fonts via `homebrew`.

The default zsh prompt is very basic, usually just the system’s hostname followed by a ‘%’.

image

But you can configure the prompt to show whatever information you want, like the current working directory, the date and time, the name of the current git branch, and whether you have changes that have not been committed, etc.

The simple, hand-made zsh prompt we create in this chapter:

image

An example of a prompt generated by another program (p10k):

image

Things you might want in your prompt:

You can copy the contents of the example file and add it to your own .zshrc file, but these options are more subjective to personal preference, so you might want to customize things a little further.

Exploring the Example Configuration

We will use print -P to test out some different prompt strings, configure a git info section, and then source the included prompt-example.zsh and test out the difference.

Open this document in a window on one side of your screen and open your terminal emulator on the other half.

Start a fresh zsh session:

zsh -df

image

Take note of the default prompt, then import the example file and observe the difference:

source ./prompt-example.zsh

image

The PS1 Variable

The shell prompt is actually defined in an environment variable that you can set in your ~/.zshrc file.

To see your current prompt-string:

echo $PS1
# %m%# 

The % characters start special sequences that will be translated to specific values when the prompt is displayed. For example, %m will be replaced with the hostname of the host system.

The Basics

You can test a prompt-string with print -P

print -P "%m%# "
# hostname% 

Here are the options used in the prompt from the example file:

Try it Out

Run the following commands:

echo $HOSTNAME
print -P "%m%# "

Try adding %d to print the current working directory, and then try with %1d instead. Try other numbers instead of just 1, maybe even try some negative numbers…

Try running man zshmisc from the prompt and then searching (with /) for EXPANSION OF PROMPT SEQUENCES to see every code that is available. Add something to your prompt-string that we haven’t covered.

Colors and Escape Sequences

The traditional way of defining styles and colors in the terminal is to use ANSI escape codes.

So if you wanted to print “HELLO” in green, bold text, with underline, you’d write something like:

echo "\033[32;1;4mHELLO\033[0m"

This is pretty crazy, but not as bad as it looks:

But zsh gives us some easier options for working with colors and styles:

print -P '%B%U%F{green}Hello%f%u%b'

OK, that doesn’t look much better, but let’s go over it:

Try it Out

Start a zsh session, but don’t import the example file just yet:

zsh -df

Try running man zshmisc from the prompt and then searching (with /) for "EXPANSION OF PROMPT SEQUENCES" to see every code that is available - and this time scroll down and look for the sub-section on ‘Visual Effects.’

Try modifying this format string %F{green}Hello%f to have two sections of text, with opposite foreground and background colors. So maybe “HELLO” in green foreground and black background, and “WORLD” in black foreground and green background. Use print -P to test it out.

HELLO WORLD

Answer
print -P "%F{green}%K{black}Hello%k%f %F{black}%K{green}World%k%f"

VCS (Git) Information

The example file includes a section that configures zsh to read information about the current git repository, and we use zstyle to configure how it will be displayed in the prompt.

I won’t explain the zstyle module, but you can run man zshmodules and search for zstyle for the official documentation, and there are a lot of good tutorials available on the internet.

I will go over some of the things that I think you may want to customize, using all of the things we’ve covered so far:

The normal git status format.

zstyle ':vcs_info:git:*' formats '%F{green} %f(%b)%F{yellow}%u%c%f'

This format string will show:

How to display the ‘staged’/’unstaged’ indicators:

If you want to use the %u and %c characters to indicate that you have pending changes, then you may want to customize the content they show. By default, they show a U and a C, but I’ve changed them to use icons from a special patched font that I have installed in my terminal emulator:

zstyle ':vcs_info:git:*' stagedstr " "
zstyle ':vcs_info:git:*' unstagedstr " "

You may want to use different icons, or entirely different format strings of some type. You can remove these two lines if you prefer the default U and C characters, or you can delete these lines and remove the %c and %u from the git status format string.

“Actions” format:

When you are performing an ‘action’, like resolving conflicts while trying to apply a merge or rebase, you can use this to show information about that operation in your prompt.

zstyle ':vcs_info:git:*' actionformats '%F{green} %f(%F{yellow}%b%f|%F{red}%a%f)'

This is the same as the normal git prompt we defined, but it says the name of the ‘action’ (“merge”, “rebase”, etc.) inside the parentheses, where we have the branch name.

Try it Out

Start a zsh session and source the example file:

zsh -df
source ./prompt-example.zsh

Try creating a new branch with git checkout -b test-branch and observe the changes to the prompt.

Now try making a change to one of the files in this repository, which should make an ‘unstaged’ change.

Now run git add FILENAME to stage that change (replace FILENAME with the name of the file that you modified).

Now you can go back to the master branch with git checkout master.

If you want, delete that test branch with git branch -D test-branch.

If you are seeing a literal “${vcs_info_msg_0_}” in your prompt string, verify the following:
  1. Ensure you are calling “autoload” for “vcs_info” BEFORE you ever try to use it.
  2. Ensure you are calling “setopt prompt_subst”. You may need to put it directly after the “autoload” command.
  3. Ensure you are using single-quotes for your PS1 string.
  4. Make sure you have defined the “precmd()” function to call “vcs_info”.
  5. Double-check your implementation against the example file.

The RPROMPT Variable

You can also define a prompt-string to display on the right-side of the command-line by setting the RPROMPT variable:

export RPROMPT='%F{blue}%t%f'

This would show the current time, in blue text, on the far right side of your command line.

image

Conditional Formats

There are a few conditional formatting options you can apply to your prompt.

Run man zshmisc from the prompt and then searching (with /) for CONDITIONAL SUBSTRINGS IN PROMPT.

There are only a fixed few variables/conditions, and the syntax is a little strange.

%(CONDITION,TRUE,FALSE)

The escape sequence starts with %(, followed by:

print -P '%0(?,0,%F{red}%?%f)'

This will print the status code of the previous command, in red, if the code was non-zero. If the code was zero, it prints a zero in the default color.

Here is the final prompt format, including conditional formatting for background jobs and the status code of the previous command.

export PS1='${vcs_info_msg_0_} %F{blue} %f%1d%1(j. %F{yellow}%j%f.)%F{blue}>%f '
export RPROMPT='<%0(?..%F{red}%?%f)%F{blue}%t%f'

If these are not sufficient, you can always call a function or another program to implement conditional formatting.

Try it Out

First, source the example prompt file:

source ./prompt-example.zsh

Type an invalid command, like ls for a directory that doesn’t exist:

ls xyz123

You should see a red status code in your prompt string.

Now try suspending a job to the background with ctrl+z:

less ./README.md

Press ctrl+z to suspend the process to the background. You should see a yellow 1 next to your prompt now.

Type fg to bring the job back to the foreground, then hit q to exit.

Prompt Configuration Applications

There are also programs and utilities that you can use to generate a more complicated, themed prompt. There are even programs that are designed to be run inside the prompt to dynamically change the prompt-string by using a language like Python.

Here are a couple that I know of:

If you want to go this way, I’d recommend starship.

The git prompts from starship and p10k can show a lot more information about the state of the repository than the simple vcs_info can, like if you’re branch is ahead of the origin, or if you have untracked files, etc. On the other hand, the operations required to get that extra info can make your prompt feel very sluggish when you are working on a large repository.

I would stay away from powerline or anything else that runs “in your prompt string.” When powerline crashes, it means you have no useful prompt, and sometimes you can’t even interact with your shell!

But you already have a lean, fast, and personally customized prompt so you don’t really need to use these.


NEXT »