By Request: ZSH config

Somebody asked for it, so here’s my zsh configuration, cobbled together from various bits around the internet.

A screenshot of the two prompts, Aarron’s, then Phil’s:
ZSH prompts

All 3 files can be downloaded here: webframp-zsh.tar.gz

The main .zshrc:

# zsh user configuration file.
# Used by: Sean Escriva <sean.escriva[AT]gmail[DOT]com>
#
ZSHROOT="${HOME}/.zsh"
WORDCHARS=${WORDCHARS:s,/,,}
umask 002 # less secure
#umask 077 # more secure
 
# vi is the editor, emacs for ZLE
bindkey -e
# or
# vi all the time
#bindkey -v
 
# MODULES
zmodload zsh/complist
autoload -Uz compinit && compinit
autoload -Uz colors && colors
autoload -Uz zsh-mime-setup && zsh-mime-setup
 
# FUNCTIONS
bindkey "\e[1~" beginning-of-line
bindkey "\e[4~" end-of-line
bindkey "\e[5~" beginning-of-history
bindkey "\e[6~" end-of-history
bindkey "\e[3~" delete-char
bindkey "\e[2~" quoted-insert
bindkey "\e[5C" forward-word
bindkey "\eOc" emacs-forward-word
bindkey "\e[5D" backward-word
bindkey "\eOd" emacs-backward-word
bindkey "\e\e[C" forward-word
bindkey "\e\e[D" backward-word
bindkey "^H" backward-delete-word
# for rxvt
bindkey "\e[8~" end-of-line
bindkey "\e[7~" beginning-of-line
# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
bindkey "\eOH" beginning-of-line
bindkey "\eOF" end-of-line
# for freebsd console
bindkey "\e[H" beginning-of-line
bindkey "\e[F" end-of-line
# completion in the middle of a line
bindkey '^i' expand-or-complete-prefix
 
# patten search history
bindkey '^R' history-incremental-pattern-search-backward
bindkey '[^R' history-incremental-pattern-search-forward
 
# OPTIONS
# may try inc_append_history instead of share_history
# require fc -RI to import new hist entries though
setopt \
autocd \
autolist \
autopushd \
autoresume \
append_history \
banghist \
beep \
correct	\
correctall \
cdablevars \
NO_clobber \
NO_checkjobs \
extendedglob \
NO_flowcontrol \
globdots \
histsavenodups \
histfindnodups \
histignorealldups \
histignorespace \
histreduceblanks \
histverify \
sharehistory \
NO_hup \
longlistjobs \
NO_mailwarning \
multios \
notify \
pathdirs \
pushdtohome	\
pushdignoredups \
pushdminus \
pushdsilent	\
rcquotes \
recexact 
 
unsetopt \
bgnice \
autoparamslash
 
# ALIASES
alias l='ls -F -h --color'
alias ls='ls -F -h --color'
alias ll='ls -l -F -h --color'
alias la='ls -a -F -h --color'
alias lla='ls -l -a -F -h --color'
alias mv='nocorrect mv'
alias cd='nocorrect cd'
alias cp='nocorrect cp'
alias mkdir='nocorrect mkdir'
alias man='nocorrect man'
alias find='noglob find'
alias gcc='nocorrect gcc'
alias scp='nocorrect scp'
alias grepc='grep --color=always'
alias myip='print ${${$(LC_ALL=C /sbin/ifconfig eth0)[7]}:gs/addr://}'
alias xp='xprop | grep "WM_WINDOW_ROLE\|WM_CLASS\|^WM_NAME"' 
 
# command equivalents
alias -g L='|less'
alias -g S='&> /dev/null &'
alias -g G='|grep'
alias -g GC='|grep --color=always'
 
# Now for the stupid aliases (mostly my stupidity)
alias sl='ls'
alias cdd='cd'
alias mmv='mv'
 
alias zshrc='vim ~/.zshrc'
alias x='startx'
alias v='vim'
alias startwin='VBoxManage startvm Vista'
alias stopwin='VBoxManage controlvm Vista savestate'
 
# suffix aliases
alias -s flac=mplayer
alias -s mp3=mplayer
alias -s ogg=mplayer
alias -s wav=mplayer
alias -s avi=mplayer
alias -s mpeg=mplayer
alias -s mpg=mplayer
alias -s wmv=mplayer
alias -s org=$BROWSER
alias -s com=$BROWSER
alias -s net=$BROWSER
alias -s html=$BROWSER
alias -s bmp=feh
alias -s png=feh
alias -s jpg=feh
alias -s jpeg=feh
alias -s gif=feh
alias -s odt=oowriter
alias -s sxw=oowriter
alias -s doc=oowriter
alias -s pdf=apvlv
alias -s pyc=python
alias -s PKGBUILD=$EDITOR
 
# COMPSYS
zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
#zstyle ':completion:*:descriptions' format "- %d -"
#zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s' # display list, below prompt.
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*:manuals.(^1*)' insert-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes
zstyle ':completion:*' list-colors ''
zstyle ':completion:*' list-colors "$LS_COLORS"
 
# caching
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path ~/.zsh/completion.cache
# remove slash if argument is a directory
zstyle ':completion:*' squeeze-slashes true
# history
zstyle ':completion:*:history-words' stop yes
zstyle ':completion:*:history-words' remove-all-dups yes
zstyle ':completion:*:history-words' list false
zstyle ':completion:*:history-words' menu yes
 
zstyle ':completion:*:descriptions' format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
zstyle ':completion:*:corrections' format $'%{\e[0;31m%}%d (errors: %e)%}'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:warnings' format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*' format 'completing %d'
zstyle ':completion:*' format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
zstyle ':completion:*' group-name ''
zstyle ':completion:*' verbose yes
 
# cd directory stack menu
zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
 
# approximation
zstyle ':completion:*' completer _complete _match _approximate
zstyle ':completion:*:match:*' original only
zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX+$#SUFFIX)/3 )) numeric )'
 
# array completion element sorting
zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
 
# ssh, scp, ping, host
test ! -d "$HOME/.ssh" && mkdir "$HOME/.ssh"
test ! -f "$HOME/.ssh/known_hosts" && touch "$HOME/.ssh/known_hosts"
test ! -f "$HOME/.ssh/config" && touch "$HOME/.ssh/config"
 
zstyle ':completion:*:(scp|rsync):*' tag-order \
        'hosts:-host hosts:-domain:domain hosts:-ipaddr:IP\ address *'
zstyle ':completion:*:(scp|rsync):*' group-order \
        users files all-files hosts-domain hosts-host hosts-ipaddr
zstyle ':completion:*:ssh:*' tag-order \
        users 'hosts:-host hosts:-domain:domain hosts:-ipaddr:IP\ address *'
zstyle ':completion:*:ssh:*' group-order \
        hosts-domain hosts-host users hosts-ipaddr
 
zstyle ':completion:*:(ssh|scp|rsync):*:hosts-host' ignored-patterns \
        '*.*' loopback localhost
zstyle ':completion:*:(ssh|scp|rsync):*:hosts-domain' ignored-patterns \
        '<->.<->.<->.<->' '^*.*' '*@*'
zstyle ':completion:*:(ssh|scp|rsync):*:hosts-ipaddr' ignored-patterns \
        '^<->.<->.<->.<->' '127.0.0.<->'
zstyle ':completion:*:(ssh|scp|rsync):*:users' ignored-patterns \
        adm bin daemon halt lp named shutdown sync
 
zstyle -e ':completion:*:(ssh|scp|ping|host|nmap|rsync):*' hosts 'reply=(
        ${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) \
                        /dev/null)"}%%[#| ]*}//,/ }
        ${=${(f)"$(cat /etc/hosts(|)(N) <<(ypcat hosts 2>/dev/null))"}%%\#*}
        ${=${${${${(@M)${(f)"$(<~/.ssh/config)"}:#Host *}#Host }:#*\**}:#*\?*}}
        )'
 
# kill
#zstyle ':completion:*:*:kill:*:processes' list-colors "=(#b) #([0-9]#)*=$color[cyan]=$color[red]"
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
zstyle ':completion:*:*:kill:*' menu yes select
zstyle ':completion:*:kill:*' force-list always
zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'
zstyle ':completion:*:kill:*' insert-ids single
zstyle ':completion:*:*:kill:*' menu yes select
zstyle ':completion:*:kill:*' force-list always
zstyle ':completion:*:processes' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'
 
# man
zstyle ':completion:*:man:*' separate-sections true
 
# mutt
if [[ -f ~/.mutt/aliases ]]; then
    zstyle ':completion:*:*:mutt:*' menu yes select
    zstyle ':completion:*:mutt:*' users ${${${(f)"$(<~/.mutt/aliases)"}#alias[[:space:]]}%%[[:space:]]*}
fi
 
# mp3 players
zstyle ':completion:*:*:mpg123:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories'
zstyle ':completion:*:*:mpg321:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories'
zstyle ':completion:*:*:ogg123:*' file-patterns '*.(ogg|OGG|flac):ogg\ files *(-/):directories'
zstyle ':completion:*:*:mocp:*' file-patterns '*.(wav|WAV|mp3|MP3|ogg|OGG|flac):ogg\ files *(-/):directories'
 
# ?
zstyle ':completion::*:(-command-|export):*' fake-parameters ${${${_comps[(I)-value-*]#*,}%%,*}:#-*-}
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
 
# ignore completion functions for commands you don't have
zstyle ':completion:*:functions' ignored-patterns '(_*|pre(cmd|exec))'
 
# Prevent CVS/SVN files/directories from being completed
zstyle ':completion:*:(all-|)files' ignored-patterns '(|*/)CVS'
zstyle ':completion:*:cd:*' ignored-patterns '(*/)#CVS'
 
# Prevent lost+found directory from being completed
zstyle ':completion:*:cd:*' ignored-patterns '(*/)#lost+found'
 
# Ignore completion functions for commands you don't have:
zstyle ':completion:*:functions' ignored-patterns '_*'
 
# Ignore same file on rm
zstyle ':completion:*:(rm|kill|diff):*' ignore-line yes
zstyle ':completion:*:rm:*' file-patterns '*:all-files'
 
# Ignore all for mcd
zstyle ':completion:*:mcd:*' ignored-patterns '*'
zstyle ':completion:*:wine:*' file-patterns '*.(exe|EXE):exe'
 
# add gnu default completions
compdef _gnu_generic ctags
 
# automagic url quoter
autoload -U url-quote-magic
zle -N self-insert url-quote-magic
 
# ENV
fpath=(
	$zdotdir/{.[z]sh/*.zwc,{.[z]sh,[l]ib/zsh}/{functions,scripts}}(N)
	$fpath
	/usr/share/zsh/${ZSH_VERSION}/[F]unctions(N)
)
 
for dirname in $fpath; do
	fns=( $dirname/*-*-(N.x:t) )
	(( $#fns )) && autoload "$fns[@]"
done
typeset -gU fpath
 
freload () {
	while (( $# )); do
		unfunction $1;
		autoload -U $1;
		shift;
	done
}
 
# For those times when we may get confused =]
setenv () {
	typeset -x "${1}${1:+=}${(@)argv[2,$#]}"
}
 
# OS specific stuff for different systems I work on.
case `uname` in
	FreeBSD)
		LSCOLORS="ExFxcxdxbxEgababagacad"
		;;
	NetBSD)
		manpath=($manpath /usr/pkg/man); export MANPATH
		;;
	Darwin)
		LSCOLORS="ExFxcxdxbxEgababagacad"
		;;
	Linux)
		manpath=($manpath /opt/man); export MANPATH
		;;
	*)
		;;
esac
 
# Manual page paths
setopt ALL_EXPORT
manpath=(/usr/man /usr/local/man /usr/share/man /usr/local/share/man)
 
# Automatically remove duplicates from these arrays
typeset -U path cdpath fpath manpath
 
# History
HISTFILE=${HOME}/.zhistory
HISTSIZE=3000 # huge hist file
SAVEHIST=3000
DIRSTACKSIZE=20 # rarely need more than that
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:/usr/games:/usr/lib/surfraw:/opt/kde/bin:/opt/java/bin:/usr/lib/git-core
HOSTNAME=`hostname`
BROWSER="/usr/bin/firefox"
PAGER=less
LESS='-RMS'
EDITOR="vim"
# Colorize STDERR red, from gentoowiki
#exec 2>>(while read line; do print '\e[91m'${(q)line}'\e[0m' > /dev/tty; done &)
# setup a bunch of fancy colors
DARCS_ALWAYS_COLOR=1
DARCS_DO_COLOR_LINES=1
LS_COLORS='no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.svgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:';
ZLS_COLORS=$LS_COLORS
GREP_COLOR='1;32' #bright green
GREP_OPTIONS='--color=auto'
CVS_RSH=ssh
LANGUAGE=
LC_ALL=en_US.UTF-8
LANG=en_US.UTF-8
LESS_TERMCAP_mb=$'\E[01;31m'
LESS_TERMCAP_md=$'\E[01;31m'
LESS_TERMCAP_me=$'\E[0m'
LESS_TERMCAP_se=$'\E[0m'                           
LESS_TERMCAP_so=$'\E[01;44;33m'                                 
LESS_TERMCAP_ue=$'\E[0m'
LESS_TERMCAP_us=$'\E[01;32m'
unsetopt ALL_EXPORT
 
# User defined functions
extract() {
    if [ -f $1 ]; then
        case $1 in
            *.tar.bz2)      tar xjvf $1     ;;
            *.tar.gz)       tar xzvf $1     ;;
            *.tgz)          tar xzvf $1     ;;
            *.bz2)          bzip2 -d $1     ;;
            *.gz)           gunzip -d $1    ;;
            *.tar)          tar xvf $1      ;;
            *.zip)          unzip $1        ;;
            *.Z)            uncompress $1   ;;
            *.rar)          unrar x $1      ;;
            *.7z)           7z x $1         ;;
            *)              echo "'$1' Error. I have no idea what to do with that";;
        esac
    else
        echo "'$1' is not a valid file"
    fi
}
 
lsarchive() {
    if [ -f $1 ]; then
        case $1 in
            *.tar.bz2)      tar jtf $1      ;;
            *.tar.gz)       tar ztf $1      ;;
            *.tar)          tar tf $1       ;;
            *.tgz)          tar ztf $1      ;;
            *.zip)          unzip -l $1     ;;
            *.rar)          rar vb $1       ;;
            *.7z)           7z l $1         ;;
            *)              echo"'$1' Error. I have no idea what to do with that";;
        esac
    else
        echo "'$1' is not a valid archive"
    fi
}
 
# quick dir change function
rationalize-dot() {
    if [[ $LBUFFER = *.. ]]; then
        LBUFFER+=/..
    else
        LBUFFER+=.
    fi
}
zle -N rationalize-dot
bindkey . rationalize-dot
 
# Set up prompt
#source $HOME/.zsh/prompt.phil
source $HOME/.zsh/prompt.aaron

Xmonad and Xmonad-contrib documentation

For personal reference, I keep haddock docs for darcs versions of xmonad and xmonad-contrib on this site.

It’s easy enough to build using:

$ cabal haddock

but if you don’t want to do that for any reason:

Offlineimap + mutt + gmail + msmtp = crazy delicious email

I’ve finally settled on the best email setup I’ve had since the fetchmail+procmail+mutt setup I used several years ago. It’s not much different and still allows me to use my absolute favorite email client, mutt. “Offlineimap is a tool to simplify your email reading” says the homepage for this deceptively simple program. With offlineimap I now have a backup of all the messages in my gmail account, mutt performance is improved (it’s much better at Maildir than direct imap access), and have synchronized my mail reading on 3 different machines.

So here’s the basics.

.offlineimaprc:

[general]
metadata = ~/.offlineimap
accounts = GmailMain
ui = Noninteractive.Quiet
 
[mbnames]
enabled = yes
filename = ~/.mutt/muttrc.mailboxes
header = "mailboxes "
peritem = =%(foldername)s
sep = " "
footer = "\n"
 
[Account GmailMain]
localrepository = GmailLocal
remoterepository = GmailRemote
 
[Repository GmailLocal]
type = Maildir
localfolders = ~/.mail/GMAIL
 
[Repository GmailRemote]
type = Gmail
remoteuser = yourname@gmail.com
remotepassfile = ~/.mailpass

.msmtprc:

account default
host smtp.gmail.com
port 587
from yourname@gmail.com
tls on
tls_starttls on
# you can google on how to find this
tls_trust_file /home/webframp/.mutt/certs/Thawte_Premium_Server_CA.pem
auth on
user yourname
password yourpassword
logfile ~/.msmtp.log

relevant bits of .muttrc:

set mbox_type=Maildir                                   # mailbox type
set hostname=gmail.com                                  # This is my domain.
 
# GMAIL+OFFLINEIMAP settings
set imap_user=sean.escriva@gmail.com
set folder=$HOME/.mail/GMAIL
set spoolfile=+/INBOX
set postponed="+[GMAIL].Drafts"
set record="+[GMAIL].Sent Mail"
 
# Mailboxes via offlineimap
source $HOME/.mutt/muttrc.mailboxes
 
set sendmail="/usr/bin/msmtp"               # Sendmail alternative

I find running offlineimap via my crontab provides a nice solution to that
compulsive mail check impulse that can easily develop. Of course I also have a
Maildir check in my dzen xmonad statusbar using the ppExtras setting of my
pretty printer:

...
  , ppExtras = [logMail]
  }
where
 logMail = dzenColorL colorPink "" . wrapL mailIcon "". padL $ maildirNew mailDir
 mailIcon = "^i(/home/webframp/.dzen/icons/dzen_bitmaps/envelope.xbm)"
 mailDir = "/home/webframp/.mail/GMAIL/INBOX"

Maybe you can glean something useful from my setup