L2 Cache

Behold the power of |!

User Tools

Site Tools


Sidebar

configuration:zsh

This is an old revision of the document!


Z shell

Introduction

I recently (201207) switched to zsh from bash. Although I liked bash I did find it lacking at times. I poked at some other shells before but never really invested time in one.

Recently a friend did show me her cool zsh configuration, so I though it may be worth some of my time.

Here you will find a few screenshots and my commented .zshrc.

Features

  • Auto-update (checked at login, max 1x per day)
  • Directory change shorthand enabled
  • Extra globbing
  • Colorization support for linux, solaris and mac os x (Or as good as I could get it)
  • Per host customizations (See example for Axion, my mac with macports)
  • Keybinds that work in xterm, putty, iterm, terminal.app and sun-color
  • Auto completion
    • kill menu
    • killall menu
    • ssh host completion with auto .ssh/config setup
    • ssh user completion, stripped most comon system users to keep the list short
  • Multiple prompts (double, minimal, gentoo and gentoo-server)
    • minimal and double themes have a UTF-8 check mark/cross character (with fall back for non-compat systems)

Screenshots

User prompt, showing of the exit code indicated and auto completion.

Root prompt, same as user but with red brackets.

Custom hostname color for Axion.

Alternative style, taking 2 lines instead of one.

Nostalgia, gentoo mode.

.zshrc

## .zshrc
# by Jorge Schrauwen <jorge@blackdot.be>
# Version 20141225008
#         YYYYMMDD###

# How to install
# curl -sk "https://docu.blackdot.be/getRaw.php?onlyCode=true&id=configuration:zsh" -o ~/.zshrc 
#
# Change Log
# - 20141225: --- - set NOFANCY_PROMPT to disable UTF-8 prompt
# - 20141225: fix - broken dual and gentoo-server themes
# - 20141225: --- - reworked flow
# - 20141225: new - local option override (.zopts)
#                   * also allows for alternate NZSHRC to be set
# - 20141225: fix - updated automatic update function
# - 20141223: fix - disable autocomplete of arguments
# - 20141223: new - disabled beep
# - 20141223: fix - disabled homedir autocomplete
# - 20141008: new - SmartOS support LX brand /native
# - 20141003: new - OpenBSD pkg_add helper
# - 20141002: --- - Solaris re-order PATH/MANPATH
# - 20141002: --- - avoid double sourcing, .zprofile -> .zlocal
# - 20140820: fix - MacOSX Yosemite ctr+r works
# - 20140727: fix - Solaris zshenable works
# - 20140727: fix - don't butcher EDITOR
# - 20140726: new - SmartOS zone support
# - 20140629: new - MacOSX pkgsrc on OSX (http://saveosx.org)
# - 20140421: new - OpenBSD color ls
# - 20131013: new - Solaris zfs compatible rsync alias
# - 20131010: --- - path cleanup
# - 20131009: new - Solaris path tweaks + colorls
# - 20130730: fix - OmniOS manpages
# - 20130716: fix - Solaris sbin handling
# - 20130629: new - OmniOS obd repository support
# - 20130625: fix - OmniOS fixed broken isaexec
# - 20130621: fix - OmniOS add sbin only when staff
# - 20130520: new - OmniOS support
# - 20120823: new - automatic update
# - 20120821: new - disable UTF-8 check-mark with .znofancy

# {{{ updater
    NZSHRC="https://docu.blackdot.be/getRaw.php?onlyCode=true&id=configuration:zsh"
    CHECK_UPDATE=1
    AUTO_UPDATE=1
# }}}

# {{{ options
    ## change directory 
    setopt auto_cd      # drop cd
    
    ## enable command correction
    setopt correct
    #setopt correct_all  

    ## prevent file overwrite
    setopt no_clobber

    ## pound sign in interactive prompt
    setopt interactive_comments 

    ## superglobs
    #setopt extended_glob
    unsetopt case_glob
    
    ## expansions performed in prompt
    setopt prompt_subst
    setopt magic_equal_subst

    ## prompt about background jobs on exit
    setopt check_jobs

    ## notify on job complete
    setopt notify
    
    ## disable beep
    unsetopt beep
    setopt no_beep
    
    # include local options
    [[ -e ~/.zopts ]] && source ~/.zopts
# }}}

# {{{ prompt
    # enable colors module
    autoload -U colors && colors

    # utf8 checkmarks
    PROMPT_CO='.'
    PROMPT_CE='!'
    case $LANG in *UTF-8)
        case $TERM in (xterm*)
            if [[ ! -z $NOFANCY_PROMPT ]] ; then
                PROMPT_CO='✓'
                PROMPT_CE='✗'
            fi
        ;; esac
    ;; esac

    [[ -z $THEME ]] && THEME=minimal
    case $THEME in
        gentoo)
            PROMPT='%(!.%{$fg_bold[red]%}.%{$fg_bold[green]%}%n@)%m %{$fg_bold[blue]%}%(!.%1~.%~) %#%{$reset_color%} '
        ;;
        gentoo_server)
            PROMPT='%(!.%{$fg_bold[red]%}.%{$fg_bold[yellow]%}%n@)%m %{$fg_bold[blue]%}%(!.%1~.%~) %#%{$reset_color%} '
        ;;
        minimal)
            PROMPT=$'%{$fg_bold[grey]%}-(%{$reset_color%}%{$fg_bold[white]%}%1~%{$reset_color%}%{$fg_bold[grey]%})-[%{$reset_color%}%(?,%{$fg_bold[green]%}$PROMPT_CO%{$reset_color%},%{$fg_bold[red]%}$PROMPT_CE%{$reset_color%})%{$fg_bold[grey]%}]-%{$reset_color%}%(!.%{$fg_bold[red]%}.%{$fg_bold[yellow]%}){%{$reset_color%} '
            RPROMPT=$'%(!.%{$fg_bold[red]%}.%{$fg_bold[yellow]%})}%{$reset_color%}%{$fg_bold[grey]%}-(%{$reset_color%}%{$fg_bold[$PROMPT_HOST_COLOR]%}%n@%m%{$reset_color%}%{$fg_bold[grey]%})-%{$reset_color%}'
        ;;
        dual)
            PROMPT=$'%{$fg_bold[grey]%}[%{$fg_bold[$PROMPT_HOST_COLOR]%}%m %{$fg_bold[grey]%}:: %(!.%{$fg_bold[red]%}.%{$fg_bold[green]%})%n%{$fg_bold[grey]%}][%{$fg_bold[white]%}%~%{$fg_bold[grey]%}]\n[%(?,%{$fg_bold[green]%}$PROMPT_CO%{$reset_color%},%{$fg_bold[red]%}$PROMPT_CE%{$reset_color%})%{$fg_bold[grey]%}]%(!.%{$fg_bold[red]%}#.%{$fg_bold[green]%}$)%{$reset_color%} '
        ;;
    esac
    unset THEME
# }}}

# {{{ history
    # history file
    HISTFILE=~/.zhistory
    HISTSIZE=10000
    SAVEHIST=10000

    # share history file
    setopt share_history
    setopt inc_append_history

    # ignore duplicates
    setopt hist_ignore_all_dups
    
    # ignore entries starting with a space
    setopt hist_ignore_space
# }}}

# {{{ keybindings
    # generic
    bindkey "\e[1~" beginning-of-line # Home
    bindkey "\e[4~" end-of-line # End
    bindkey "\e[5~" beginning-of-history # PageUp
    bindkey "\e[6~" end-of-history # PageDown
    bindkey "\e[2~" quoted-insert # Ins
    bindkey "\e[3~" delete-char # Del
    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 "\e[Z" reverse-menu-complete # Shift+Tab
    bindkey '^R' history-incremental-search-backward
    bindkey ' ' magic-space # becasue I am lazy

    # for rxvt
    bindkey "\e[7~" beginning-of-line # Home
    bindkey "\e[8~" end-of-line # End

    # for non RH/Debian xterm, can't hurt for RH/Debian xterm
    bindkey "\eOH" beginning-of-line
    bindkey "\eOF" end-of-line

    # for freebsd/darwin console
    bindkey "\e[H" beginning-of-line
    bindkey "\e[F" end-of-line
# }}}

# {{{ auto completion
    ## base
    autoload -U compinit && compinit

    ## complete from withing word
    setopt complete_in_word

    ## complete aliases
    setopt complete_aliases

    ## pretty menu's
    zstyle ':completion:*' menu select=1
    zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
    setopt auto_menu    # show menu on 2nd <tab>
    setopt list_rows_first  # use row list if possible

    ## Ignore completions for commands that we dont have
    zstyle ':completion:*:functions' ignored-patterns '_*'

    ## enable case-insensitive completion
    zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'

    ## enable caching
    zstyle ':completion::complete:*' use-cache on
    zstyle ':completion::complete:*' cache-path ~/.zcache

    ## Prevent re-suggestion
    zstyle ':completion:*:rm:*' ignore-line yes
    zstyle ':completion:*:scp:*' ignore-line yes
    zstyle ':completion:*:ls:*' ignore-line yes

    ## enable killall menu
    zstyle ':completion:*:processes-names' command 'ps -u $(whoami) -o comm='
    zstyle ':completion:*:processes-names' menu yes select
    zstyle ':completion:*:processes-names' force-list always    

    ## enable kill menu
    zstyle ':completion:*:kill:*' command 'ps -u $(whoami) -o pid,pcpu,pmem,cmd'
    zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;32'
    zstyle ':completion:*:*:kill:*' menu yes select
    zstyle ':completion:*:kill:*' force-list always
    zstyle ':completion:*:kill:*' insert-ids single

    ## enable make completion
    compile=(all clean compile disclean install remove uninstall)
    compctl -k compile make

    ## ssh host completion
    if [ ! -f ~/.ssh/config ]; then
        [ -f ~/.ssh/known_hosts ] && rm ~/.ssh/known_hosts
        mkdir -p ~/.ssh
        echo "HashKnownHosts no" >>! ~/.ssh/config
        chmod 0600 ~/.ssh/config
    fi
    zstyle -e ':completion::*:ssh:*:hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })'
    zstyle ':completion:*:ssh:*' group-order hosts-domain hosts-host users hosts-ipaddr

    ## ssh user completion cleanup
    zstyle ':completion:*:ssh:*:users' ignored-patterns \
        adm alias apache at bin cron cyrus daemon distcache exim ftp games gdm \
        guest gopher haldaemon halt mail man messagebus mysql named news nobody nut \
        nfsnobody lp operator portage postfix postgres postmaster qmaild qmaill qmailp \
        qmailq qmailr qmails rpmbuild rpc rpcuser shutdown smmsp squid sshd sync saslauth \
        uucp vcsa vpopmail xfs 
# }}}

# {{{ functions
    # update .zshrc
    zshupdate() { 
        # main
        if [ -z "`which curl`" ]; then
            echo 'Please install curl!'
            exit
        fi
        NV=`curl -sk ${NZSHRC} | head -n3 | tail -n1 | awk '{ print $3 }'`
        OV=`cat ~/.zshrc | head -n3 | tail -n1 | awk '{ print $3 }'`
        [ -z "${NV}" ] && NV=0
        
        if [ ${NV} -gt ${OV} ]; then
            echo -n "[>>] Updating from ${OV} to ${NV} ...\r"
            mv ~/.zshrc ~/.zshrc.old
            curl -sk ${NZSHRC} -o ~/.zshrc
            source ~/.zshrc
            echo '[OK]'
        else
            echo "[OK] No update needed."
        fi
    }

    # auto update check
    if [ ${CHECK_UPDATE} -gt 0 ]; then
        if [ `find ~/.zshrc -mmin +1440` ]; then
            touch ~/.zshrc
            NV=`curl -sk -m 3 ${NZSHRC} | head -n3 | tail -n1 | awk '{ print $3 }'`
            OV=`cat ~/.zshrc | head -n3 | tail -n1 | awk '{ print $3 }'`
            [ -z "${NV}" ] && NV=0
        
            if [ ${NV} -gt ${OV} ]; then
                if [ ${AUTO_UPDATE} -gt 0 ]; then
                    zshupdate
                else
                    echo "Please run zshupdate to update .zshrc to version ${NV}!"
                fi
            fi
        fi
    fi

    # remove ssh known_hosts key
    delete_sshhost() {
        if [[ -z "$1" ]] ; then
            echo "usage: \e[1;36mdelete_sshhost \e[1;0m< host >"
            echo "       Removes the specified host from ssh known host list"
        else
            sed -i -e "/$1/d" $HOME/.ssh/known_hosts
        fi
    }
# }}}

# {{{ variables
    # preferences
    which nano &> /dev/null ; [ $? -eq 0 ] && export EDITOR='nano'
    which vim &> /dev/null ; [ $? -eq 0 ] && export EDITOR='vim'
    export PAGER='less'
# }}}

# {{{ aliases
    # nano wrapping
    which nano &> /dev/null ; [ $? -eq 0 ] && alias nano='nano -w'

    # default for ls
    alias ll='ls -l'
    alias lr='ls -R'

    case $OSTYPE in solaris*)
        alias zfs_rsync='rsync -avAPh'
        alias zfs_rsync+='rsync -avAPh --delete'
    ;; esac

    # include local aliases
    [[ -e ~/.aliasses ]] && mv ~/.aliasses ~/.aliases
    [[ -e ~/.aliases ]] && source ~/.aliases
# }}}

# {{{ advanced
    ## fix url quote's
    if [[ ${ZSH_VERSION//\./} -ge 420 ]] ; then
         autoload -U url-quote-magic
         zle -N self-insert url-quote-magic
    fi

    ## os specific
    case $OSTYPE in linux*)
        # detect root or staff
        [ $UID -eq 0 ] && WANT_SBIN=1
        [ $(groups | grep -c sudo) -gt 0 ] && WANT_SBIN=1
        [ $(groups | grep -c wheel) -gt 0 ] && WANT_SBIN=1
  
        # colorization
        [ -f /etc/DIR_COLORS ] && eval $(dircolors -b /etc/DIR_COLORS)
        [ -f ~/.dir_colors ] && eval $(dircolors -b ~/.dir_colors)

        if [ -n "${LS_COLORS}" ]; then
            export ZLSCOLORS="${LS_COLORS}"
            alias ls='ls --color=auto'
            alias grep='grep --color=auto'
        fi
  
        # LX BrandZ
        [ -d /native/usr/bin ] && export PATH=$PATH:/native/usr/bin
        [ -d /native/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=$PATH:/native/sbin
        [ -d /native/usr/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=$PATH:/native/usr/sbin
    ;; esac
    case $OSTYPE in solaris*)
        # detect root or staff
        [ $UID -eq 0 ] && WANT_SBIN=1
        [ $(groups | grep -c staff) -gt 0 ] && WANT_SBIN=1
        [ $(groups | grep -c sysadmin) -gt 0 ] && WANT_SBIN=1
        export MANPATH=/usr/share/man

        # add /usr/sbin if wanted
        [ $(echo $PATH | grep -c '/usr/sbin:')  -eq 0 ] && 
            [[ -n $WANT_SBIN ]] && export PATH=$PATH:/usr/sbin

        # check for gnu
        export PATH=$(echo $PATH | /bin/sed -r 's#:/usr/gnu/s?bin##g')
        [ -d /usr/gnu/bin ] && export PATH=$PATH:/usr/gnu/bin
        [ -d /usr/gnu/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=$PATH:/usr/gnu/sbin
  
        # check for obd repository (omnios)
        export PATH=$(echo $PATH | /bin/sed -r 's#/opt/obd/s?bin:##g')
        export MANPATH=$(echo $MANPATH | /bin/sed -r 's#/opt/obd/share/man:##g')
        [ -d /opt/obd/bin ] && export PATH=$PATH:/opt/obd/bin
        [ -d /opt/obd/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=$PATH:/opt/obd/sbin
        [ -d /opt/obd/share/man ] && export MANPATH=$MANPATH:/opt/obd/share/man
  
        # check for pkgsrc (smartos)
        export PATH=$(echo $PATH | /bin/sed -r 's#/opt/local/s?bin:##g')
        [ -d /opt/local/bin ] && export PATH=/opt/local/bin:$PATH
        [ -d /opt/local/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=/opt/local/sbin:$PATH
        [ -d /opt/local/man ] && export MANPATH=/opt/local/man:$MANPATH

        # check for omniti repository (omnios)
        export PATH=$(echo $PATH | /bin/sed -r 's#/opt/omni/s?bin:##g')
        export MANPATH=$(echo $MANPATH | /bin/sed -r 's#/opt/omni/share/man:##g')
        [ -d /opt/omni/bin ] && export PATH=$PATH:/opt/omni/bin
        [ -d /opt/omni/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=$PATH:/opt/omni/sbin
        [ -d /opt/omni/share/man ] && export MANPATH=$MANPATH:/opt/omni/share/man

        # check for sfw
        export PATH=$(echo $PATH | /bin/sed -r 's#:/usr/sfw/s?bin##g')
        [ -d /usr/sfw/bin ] && export PATH=$PATH:/usr/sfw/bin

        # check for local
        export PATH=$(echo $PATH | /bin/sed -r 's#/usr/local/s?bin:##g')
        [ -d /usr/local/bin ] && export PATH=/usr/local/bin:$PATH
        [ -d /usr/local/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=/usr/local/sbin:$PATH

        # check for opencsw
        export PATH=$(echo $PATH | /bin/sed -r 's#:/opt/csw/s?bin##g')
        [ -d /opt/csw/bin ] && export PATH=$PATH:/opt/csw/gnu:/opt/csw/bin
        [ -d /opt/csw/sbin ] && [[ -n $WANT_SBIN ]] && export PATH=$PATH:/opt/csw/sbin

        # colorization
        [ "$(which ls)" = "/usr/bin/ls" ] && alias ls='ls --color'

        # selective gnu / colorization
        [ "$(which ls)" = "/usr/gnu/bin/ls" ] && alias ls='/usr/gnu/bin/ls --color=auto'
        [ -e /usr/gnu/bin/grep ] && alias grep='/usr/gnu/bin/grep --color=auto'
        [ -e /usr/gnu/bin/sed ] && alias sed='/usr/gnu/bin/sed'
        [ -e /usr/gnu/bin/diff ] && alias diff='/usr/gnu/bin/diff'
        [ -e /usr/gnu/bin/tar ] && alias tar='/usr/gnu/bin/tar'
        [ -e /usr/gnu/bin/rm ] && alias rm='/usr/gnu/bin/rm'
    ;; esac
    case $OSTYPE in openbsd*)
        # set PKG_PATH
        export PKG_PATH=http://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/  

        # colorization
        [ -e /usr/local/bin/colorls ] && alias ls='/usr/local/bin/colorls -G'
    ;; esac
    case $OSTYPE in darwin*)
        # colorization
        export CLICOLOR=1
        alias ls='ls -G'

        # macports (with gnu)
        if [ -e /opt/local/bin/port ]; then
            export PATH=/opt/local/libexec/gnubin:/opt/local/bin:/opt/local/sbin:$PATH
            export MANPATH=/opt/local/share/man:$MANPATH
            if [ -f ~/.dir_colors ]; then
                eval $(dircolors -b ~/.dir_colors)
                export ZLSCOLORS="${LS_COLORS}"
                unalias ls &> /dev/null
                alias ls='ls --color=auto'
            fi
            if [ -e /opt/local/bin/python2 ]; then
                alias python='/opt/local/bin/python2'
            fi
        fi
  
        # pkgsrc
        if [ -e /usr/pkg/bin/pkgin ]; then
            export PATH=/usr/pkg/gnu/bin:/usr/pkg/bin:/usr/pkg/sbin:$PATH
            export MANPATH=/usr/pkg/man:$MANPATH
            if [ -f ~/.dir_colors ]; then
                eval $(dircolors -b ~/.dir_colors)
                export ZLSCOLORS="${LS_COLORS}"
                unalias ls &> /dev/null
                alias ls='ls --color=auto'
            fi
            alias pkgin='sudo pkgin'
        fi
    ;; esac
    
    # zsh shortcuts
    case $OSTYPE in linux*|darwin*|openbsd*)
        alias zshenable='chsh -s $(which zsh)'
        alias zshdisable='chsh -s $(which bash)'
    ;; esac 
    case $OSTYPE in solaris*)
        alias zshenable='pfexec /usr/sbin/usermod -s $(which zsh) $(id -n -u)'
        alias zshdisable='pfexec /usr/sbin/usermod -s $(which bash) $(id -n -u)'
    ;; esac 

    ## host specific
    case ${HOST:r} in
        (axion*|tachyon*)
            # add a little info banner
            if [[ $SHLVL -eq 1 ]] ; then
                clear
                echo
                print -P "\e[1;33m Welcome to: \e[1;34m%m"
                print -P "\e[1;33m Running: \e[1;34m`uname -srm`\e[1;33m on \e[1;34m%l"
                print -P "\e[1;33m It is:\e[1;34m %D{%r} \e[1;33m on \e[1;34m%D{%A %b %f %G}"
                echo
                tput sgr0
            fi

            # proper UTF-8
            export LANG=en_US.UTF-8

            # host color
            PROMPT_HOST_COLOR=green
        ;;
        (artemis*|monolith*)
            PROMPT_HOST_COLOR=red
        ;;
        *)
            # default host color
            PROMPT_HOST_COLOR=blue
        ;;  
    esac
  
  ## local configuration
  [[ -e ~/.zlocal ]] && source ~/.zlocal
# }}}
configuration/zsh.1419509133.txt.gz · Last modified: 2014/12/25 13:05 by sjorge