Pimp your ZSH

I’ve been using ZSH for just over a year now, thanks to oh-my-zsh, but I realised that I probably wasn’t using it to it’s full potential. It’s the same kind of thing as when I tried to use Vim, I just forked someone else’s settings and didn’t realise just what was going on.

A few weeks ago, I decided to start from scratch and see what I could come up with. I’m already back to what I used, and I understand how it all works too!

Autocomplete

The first important line is this one:

autoload -Uz compinit && compinit

Without it, any completion files we add won’t be used. Completion in ZSH is awesome, so I’d definitely recommend using this one. Here’s an example of completion when typing git<tab><tab>.

$ git<tab><tab> 
add                 -- add paths to the index
am                  -- apply patches from a mailbox (cooler than applymbox)
annex               -- manage files without tracking content
annotate            -- annotate file lines with commit info
apply               -- apply patch on a git index file and a work tree
applymbox           -- apply patches from a mailbox

Setting up your prompt

One of the main reasons I started using oh-my-zsh was for the prompts it provided. I managed to build a prompt I was happy with, using the following functions:

autoload -U colors && colors

function prompt_char {
    git branch >/dev/null 2>/dev/null && echo '±' && return
    hg root >/dev/null 2>/dev/null && echo '☿' && return
    echo '$'
}

function git_branch {
    BRANCH="$(git symbolic-ref HEAD 2>/dev/null | cut -d'/' -f3)"
    if ! test -z $BRANCH; then
        COL="%{$fg[green]%}" # Everything's fine
        [[ $(git log origin/master..HEAD 2> /dev/null ) != "" ]] && COL="%{$fg[blue]%}" # We have changes to push
        [[ $(git status --porcelain 2> /dev/null) != "" ]] && COL="%{$fg[red]%}" # We have uncommited changes
        echo "$COL$BRANCH"
    fi
}

function precmd() {
    NAME=""
    if [[ $(whoami) != "michael" ]]; then; NAME="%n%{$reset_color%}@"; fi;

    PROMPT="%{$fg[red]%}$NAME%{$fg[green]%}%m %{$fg[yellow]%}%~ %{$reset_color%}% $(prompt_char) "
    RPROMPT="$(git_branch)%{$reset_color%}%"
}

The $fg array is provided by the line:

autoload -Uz compinit && compinit

What this does, is load up some colour code escape sequences and gives them nicer names for you to use.

Vim mode

Once you start using vim, you get frustrated when your normal movement commands won’t work. The following options enable vim mode, and remap jj to <esc>.

bindkey -v
bindkey -M viins 'jj' vi-cmd-mode

ZSH Syntax Highlighting

This one’s awesome. It highlights what you’re tying in real time. If the program doesn’t exist, the text is red – if it does, it’s green. It highlights matching brackets, text inside quotes, loads of stuff.

To use it, clone zsh-syntax-highlighting from Github and add the following commands to your .zshrc. They’ll enable the common highlighters, and add a warning highlight when you try and use rm -rf.

source ./zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern cursor)
ZSH_HIGHLIGHT_PATTERNS+=('rm -rf *' 'fg=white,bold,bg=red')

And more?

That’s about as far as I’ve come with my .zshrc for now. It does everything I knew I wanted it to do (and even some stuff I didn’t know I wanted until it did it). If I find anything else that’s cool, I’ll be sure to blog about it.

Michael is a polyglot software engineer, committed to reducing complexity in systems and making them more predictable. Working with a variety of languages and tools, he shares his technical expertise to audiences all around the world at user groups and conferences. You can follow @mheap on Twitter

Thoughts on this post

Thanks for the “source ./zsh-syntax-highlighting/zsh-syntax-highlighting.zsh” line. I’ve been tearing my hair out trying to get this working. That did it!

Leave a comment?

Leave a Reply