You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

3.7 KiB

title tags description date draft
Building a ZSH prompt [Linux ZSH] There are many frameworks out there to help you build a prompt, I thought I'd see how far I could get without one. 2020-03-24 true

Until recently, I was using oh-my-zsh with the Power Level 9k prompt.

In part of my effort to understand how different parts of my system works, and to reduce my reliance on some libraries, I decided to see if I could get what I needed without them. In this blog post, I am going to focus on my prompt configuration.

If you want to follow along, my configuration can be found in my dotfiles.

My prompt currently looks something like this:

My Prompt

Basics

Zsh simply prints the variables PROMPT and RPROMPT when drawing the left and right prompts respectively. PROMPT is roughly equivalent to the PS1 variable in bash.

By setting the variable, you can change how the prompt works. E.g.

oldPrompt $ PROMPT="new prompt > "
new prompt > ls
Documents	Downloads	GitRepos
new prompt > █

ZSH Hooks

Zsh has a concept called hooks. These allow you to run a function (or functions) automatically at certain times.

For the purposes of setting my prompt, I want to run a function to set PROMPT and RPROMPT before the prompt is drawn. This can be done with the precmd hook.

set_prompts(){
	PROMPT="$ "
	RPROMPT=""
}
zle -N set_prompts
autoload -U add-zsh-hook
add-zsh-hook precmd set_prompts

This defines a function set_prompts and it will be run just before the prompt is drawn, every time. We can therefore use it to build the prompt.

Drawing segments

I like the arrow style that was made popular by Powerline. To achieve this, you will need a font that contains the powewline glyphs. If you don't have one, I highly recommend the Nerd Fonts project that aggregates a lot of icons as well as the powerline symbols. It even includes a script that allows you to add them to your favourite font.

Exit Code

In ZSH (and most other shells), the exit code of the previous command is available in the special $? variable. If we want the exit code of the last command run, we need to assign this to a variable first.

# Get the return status of the previous command
local RETVAL=$?

Git

I use Git a lot. It is useful to tell, at a glance, which branch I'm on, which tag I'm on and what the state of repository is. The function is quite simple:

prompt_git(){
	local repoTopLevel="$(command git rev-parse --show-toplevel 2> /dev/null)"
	if [ -n "$repoTopLevel" ]; then
		local branch="$(git branch --show-current 2> /dev/null)"
		local tag="$(git describe --tags --exact-match HEAD 2> /dev/null)"
		local color="green"
		local ret=""
		[ -n "$branch" ] && ret="$branch "
		[ -n "$tag" ] && ret+="$tag "
		[ -n "$ret" ] || ret="$(git rev-parse --short HEAD 2> /dev/null)"
		local repoTopLevel="$(command git rev-parse --show-toplevel 2> /dev/null)"
		local untrackedFiles=$(command git ls-files --others --exclude-standard "${repoTopLevel}" 2> /dev/null)
		local modified=$(command git diff --name-only 2> /dev/null)
		local staged=$(command git diff --staged --name-only 2> /dev/null)

		if [ -n "$untrackedFiles" ]; then
			ret+=" "
			color="orange1"
		fi
		if [ -n "$modified" ]; then
			ret+=" "
			color="orange1"
		fi
		if [ -n "$staged" ]; then
			ret+=" "
			color="orange1"
		fi
	fi
	ret="$(echo "$ret" | sed -e 's/ *$//')"
	echo "$ret"
	echo "$color"
}