Rewriting my .zshrc

Vincent Bernat

Ten years ago, I started to use Zsh, a shell de­signed for in­ter­ac­tive use but which is also pow­er­ful for script­ing us­age. I had a fairly com­pre­hen­sive .zshrc file split in sev­eral parts. I have de­cided to re­write it for sev­eral reasons:

  1. I did not take ad­van­tage of sev­eral fea­tures of Zsh, like some ad­vanced pa­ram­e­ter ex­pan­sion, ar­rays, arith­metic ex­pres­sions and other built-in fea­tures. There were a lot of | head, | awk, | sed that could be re­placed by some Zsh wiz­ardry (some­thing eas­ier to read like ${${(f)~~"$(< /​etc/​hosts)"}%%\#*}).

  2. It con­tained a lot of hacks to make things work on some odd/old set­ups. I was not re­ally sure that these hacks are use­ful any­more. It also con­tained a lot of con­di­tion­als where some parts of the code were ex­e­cuted de­pend­ing on the hostname.

I have dis­cov­ered oh-my-zsh, a nice project try­ing to pro­vide a generic and flex­i­ble Zsh con­fig­uration:

A com­mu­nity-driven frame­work for man­ag­ing your zsh con­fig­u­ra­tion. In­cludes 40+ op­tional plug­ins (rails, git, OSX, hub, capis­trano, brew, ant, mac­ports, etc), over 80 ter­mi­nal themes to spice up your morn­ing, and an auto-up­date tool so that makes it easy to keep up with the lat­est up­dates from the community.

The idea of such a project is to fork it and make the changes that you need. I was pre­vi­ously hack­ing around Phil!’s Zsh Prompt for my prompt. oh-my-zsh con­tains a close theme (jonathan). Neat. How­ever, I de­cided to write my .zshrc from scratch (but with some snip­pets stolen from oh-my-zsh). Why? Mostly be­cause I want to pre­cisely con­fig­ure Zsh. Even with its plugin ar­chi­tec­ture and its over­ride mech­a­nism, oh-my-zsh pro­vides some fea­tures (op­tions, aliases, func­tions) that I do not want. Thanks to git, you can fork and make any lo­cal changes you want but since I would have mod­i­fied most of the files, it seemed eas­ier to just start from scratch.

I have pub­lished the re­sult on GitHub. You can use it as is, fork it or (bet­ter) steal and adapt some snip­pets for your own us­age. Here is the manda­tory screen­shot for the prompt (not much space left for the commands):

My Zsh prompt
My Zsh prompt

Up­date (2013-02)

Since I am now us­ing awe­some win­dow man­ager, I have dropped the right part of the prompt be­cause it does not be­have well when re­siz­ing win­dows. You can get the pre­vi­ous prompt by check­ing out tag before-awesome. I have then switched to a pow­er­line prompt. This kind of prompt needs a spe­cial font. To get the pre­vi­ous prompt, check­out tag before-powerline. Here is what the new prompt looks like:

Screenshot of Zsh prompt with powerline font
Zsh prompt with powerline font

Here is a short snip­pet used to se­lect a sen­si­ble EDITOR de­pend­ing on what is avail­able. It uses anony­mous func­tions (to re­strict the scope of lo­cal vari­ables), ar­rays and flags in pa­ram­e­ter ex­pan­sion. For an­other ex­am­ple, take a look at how I se­lect a valid locale.

() {
    local -a editors
    local editor
    editors=(
        "emacs23 -Q -D -nw" # Fast emacs
        "jove" "mg" "jed"   # Emacs clone
        "vim" "vi"          # vi
        "editor")           # fallback
    for editor in $editors; do
        (( $+commands[$editor[(w)1]] )) && {
            export EDITOR=$editor
            break
        }
    done
}

Enjoy!

Up­date (2011-07)

Anony­mous func­tions were in­tro­duced in Zsh 4.3.7. Older ver­sions do not sup­port them. A work­around is to use a clas­sic func­tion instead:

__() {
    local -a editors
    local editor
    ...
} && __