EDIT: I have moved away from Prezto and now use my own minimal ZSH settings.
Zsh is an amazing shell, and Oh-my-zsh is very good at showcasing its power without having to dive into too much configuration. I recommend it to Zsh first-timers: within minutes they can enjoy autocompletion on steroids, crazy prompt tweaking, git integration as well as many other plugins.
BUT. It’s God. Damn. Slow!
Wanna spend the night happily coding and hacking in the “zone”? Here, wait for 1 long second (or more) whenever you open up a new terminal window/tab. Are you triggering tab autocompletion? Oh boy. Come back tomorrow.
Enter Prezto, a.k.a the “Instantly Awesome Zsh”. It began as a fork of Oh-my-zsh, but was later completely rewritten with optimization in mind, and moved to its own repo.
Here’s how I migrated in order to have the exact same behavior as before, while still having a fast shell. Yes, I like to have my cake and eat it too.
Installation
Very straightforward:
- Backup your existing configuration:
~/.oh-my-zsh
,~/.zshrc
and your possible other dotfiles - Uninstall Oh-my-zsh by running
uninstall_oh_my_zsh
- Install Prezto by following the quick instructions on the github repo
Done. You now have a bunch of symlinked .z<something>
dotfiles in your home
folder.
Fiddling with the dotfiles
-
If it annoys you, remove the possible example instructions in
~/.zlogin
and~/.zlogout
(such as displaying a fortune every time you login) -
Put back all your aliases and other customizations into
~/.zshrc
:source ~/.zprezto/init.zsh export SUBLIME=subl export EDITOR="$SUBLIME --wait" export VISUAL=$EDITOR export LSCOLORS="exfxcxdxbxegedabagacad" ... alias ll="ls -lh" alias la="ls -A" alias gl="git pull --rebase" ...
-
If you like to organize your exports/aliases/etc into separate files, have a look at the other dotfiles. I personally don’t do that and just have one massive
~/.zshrc
.
Customizing the prompt
Now to the fun part!
Prezto contains half a dozen example themes compared to the 140 (!) ones of Oh-my-zsh. If you have a custom prompt like me, you will need to tinker a bit.
My theme is pretty minimalist: just display the current path followed by $
and a space. When in a Git repo, I like to display the branch name followed by
a dirty/clean indicator like so:
At the time of writing, most Prezto themes use vcs_info
which can detect
staged and unstaged changes (i.e. a dirty state). But there’s no hook for a
clean state, so when there are no changes, the prompt will just display
nothing. I would much rather have a satisfying green little tick.
For this, we need to use git-info
from the Prezto git
plugin. I ended up
with the following:
function prompt_jerome_precmd {
git-info
}
function prompt_jerome_setup {
setopt LOCAL_OPTIONS
unsetopt XTRACE KSH_ARRAYS
prompt_opts=(cr percent subst)
# Load required functions.
autoload -Uz add-zsh-hook
# Add hook for calling git-info before each command.
add-zsh-hook precmd prompt_jerome_precmd
# Set git-info parameters.
zstyle ':prezto:module:git:info' verbose 'yes'
zstyle ':prezto:module:git:info:branch' format '%F{green}%b%f'
zstyle ':prezto:module:git:info:clean' format ' %F{green}✔%f'
zstyle ':prezto:module:git:info:dirty' format ' %F{red}✗%f'
zstyle ':prezto:module:git:info:keys' format \
'prompt' ' %F{green}(%f$(coalesce "%b" "%p" "%c")${git_info[rprompt]}%s%F{green})%f' \
'rprompt' '%C%D'
# Define prompts.
PROMPT='%~${(e)git_info[prompt]}$ '
RPROMPT=''
}
prompt_jerome_setup "$@"
I then saved the theme in
~/.zprezto/modules/prompt/functions/prompt_jerome_setup
and made Prezto use it by having this line in ~/.zpreztorc
:
zstyle ':prezto:module:prompt' theme 'jerome'
Done.
Last bits and pieces
-
I added
history-substring-search
andgit
to the~/.zpreztorc
plugin list:... zstyle ':prezto:load' pmodule \ 'environment' \ 'terminal' \ 'editor' \ 'history' \ 'directory' \ 'spectrum' \ 'utility' \ 'completion' \ 'prompt' \ 'history-substring-search' \ 'git' ...
history-substring-search
: when pressing up/down arrows, completes the beginning of a command by searching in the history.
git
: adds useful aliases and functions like thegit-info
one that we discussed above. -
When pressing tab to complete a command, I didn’t like the category menus, so I commented these lines out in
~/.zprezto/modules/completion/init.zsh
:... # Group matches and describe. zstyle ':completion:*:*:*:*:*' menu select # zstyle ':completion:*:matches' group 'yes' # zstyle ':completion:*:options' description 'yes' # zstyle ':completion:*:options' auto-description '%d' # zstyle ':completion:*:corrections' format ' %F{green}-- %d (errors: %e) --%f' # zstyle ':completion:*:descriptions' format ' %F{yellow}-- %d --%f' # zstyle ':completion:*:messages' format ' %F{purple} -- %d --%f' # zstyle ':completion:*:warnings' format ' %F{red}-- no matches found --%f' # zstyle ':completion:*:default' list-prompt '%S%M matches%s' # zstyle ':completion:*' format ' %F{yellow}-- %d --%f' # zstyle ':completion:*' group-name '' # zstyle ':completion:*' verbose yes ...
I also modified this line in order to have red diretories when autocompleting the
cd
command:# Directories zstyle ':completion:*:default' list-colors ''
-
In my
~/.zshrc
, I added these zsh options:unsetopt CORRECT # Disable autocorrect guesses. Happens when # typing a wrong command that may look like # an existing one. expand-or-complete-with-dots() { # This bunch of code displays red dots when echo -n "\e[31m......\e[0m" # autocompleting a command with the tab key, zle expand-or-complete # "Oh-my-zsh"-style. zle redisplay } zle -N expand-or-complete-with-dots bindkey "^I" expand-or-complete-with-dots
Wrapping up
That’s it, you now have a fast zsh that behaves like before!
I skipped some minor configurations in this article, so if you want to review
exactly what I’ve done (or if you want to know what kind of crazy stuff I put
in my ~/.zshrc
), have a look at the commits in my Prezto fork.
Enjoy!
EDIT: Hacker News thread