ZSH: The Z Shell

The order of files we’re using here

/etc/zsh/zhsenv
$ZDOTDIR/.zshenv
/etc/zsh/zshrc
$ZDOTDIR/.zshrc

The zshenv to rule them all

Let’s create our /etc/zsh/zhsenv file. This is where zsh starts, it’s the first file that’s read. Here we will define our XDG (Cross-desktop Group) compatibility directories and define where we’ll put the rest of our ZSH configs.

cat << EOF > /etc/zsh/zshenv
export XDG_CACHE_HOME="\$HOME/.cache"
export XDG_CONFIG_HOME="\$HOME/.config"
export XDG_DATA_HOME="\$HOME/.local/share"
export XDG_STATE_HOME="\$HOME/.local/state"

export ZDOTDIR="\$XDG_CONFIG_HOME"/zsh
EOF

The global zshrc, things to execute for everyone

cat << EOF > /etc/zsh/zshrc
# System-wide profile for interactive zsh(1) shells.

# Correctly display UTF-8 with combining characters.
if [[ "\$(locale LC_CTYPE)" == "UTF-8" ]]; then
    setopt COMBINING_CHARS
elif grep -qi -E "utf-8|utf8" /etc/locale.conf; then
    setopt COMBINING_CHARS
fi

# Disable the log builtin, so we don't conflict with /usr/bin/log
disable log

# Save command history
HISTFILE="$ZDOTDIR"/.zsh_history
HISTSIZE=5000
SAVEHIST=5000

# No beep on error
unsetopt BEEP

setopt ALWAYS_TO_END
setopt AUTO_MENU
setopt CORRECT
setopt CORRECT_ALL
setopt EXTENDED_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_SPACE
setopt INC_APPEND_HISTORY_TIME
setopt INTERACTIVE_COMMENTS
setopt NO_CASE_GLOB

bindkey -e
bindkey "^[[H"  beginning-of-line
bindkey "^[[F"  end-of-line
bindkey "^[[3~" delete-char
bindkey "^[[A"  up-line-or-search
bindkey "^[[B"  down-line-or-search

# Use keycodes (generated via zkbd) if present, otherwise fallback on
# values from terminfo
typeset -g -A key

[[ -n "$terminfo[kf1]"   ]] && key[F1]=$terminfo[kf1]
[[ -n "$terminfo[kf2]"   ]] && key[F2]=$terminfo[kf2]
[[ -n "$terminfo[kf3]"   ]] && key[F3]=$terminfo[kf3]
[[ -n "$terminfo[kf4]"   ]] && key[F4]=$terminfo[kf4]
[[ -n "$terminfo[kf5]"   ]] && key[F5]=$terminfo[kf5]
[[ -n "$terminfo[kf6]"   ]] && key[F6]=$terminfo[kf6]
[[ -n "$terminfo[kf7]"   ]] && key[F7]=$terminfo[kf7]
[[ -n "$terminfo[kf8]"   ]] && key[F8]=$terminfo[kf8]
[[ -n "$terminfo[kf9]"   ]] && key[F9]=$terminfo[kf9]
[[ -n "$terminfo[kf10]"  ]] && key[F10]=$terminfo[kf10]
[[ -n "$terminfo[kf11]"  ]] && key[F11]=$terminfo[kf11]
[[ -n "$terminfo[kf12]"  ]] && key[F12]=$terminfo[kf12]
[[ -n "$terminfo[kf13]"  ]] && key[F13]=$terminfo[kf13]
[[ -n "$terminfo[kf14]"  ]] && key[F14]=$terminfo[kf14]
[[ -n "$terminfo[kf15]"  ]] && key[F15]=$terminfo[kf15]
[[ -n "$terminfo[kf16]"  ]] && key[F16]=$terminfo[kf16]
[[ -n "$terminfo[kf17]"  ]] && key[F17]=$terminfo[kf17]
[[ -n "$terminfo[kf18]"  ]] && key[F18]=$terminfo[kf18]
[[ -n "$terminfo[kf19]"  ]] && key[F19]=$terminfo[kf19]
[[ -n "$terminfo[kf20]"  ]] && key[F20]=$terminfo[kf20]
[[ -n "$terminfo[kbs]"   ]] && key[Backspace]=$terminfo[kbs]
[[ -n "$terminfo[kich1]" ]] && key[Insert]=$terminfo[kich1]
[[ -n "$terminfo[kdch1]" ]] && key[Delete]=$terminfo[kdch1]
[[ -n "$terminfo[khome]" ]] && key[Home]=$terminfo[khome]
[[ -n "$terminfo[kend]"  ]] && key[End]=$terminfo[kend]
[[ -n "$terminfo[kpp]"   ]] && key[PageUp]=$terminfo[kpp]
[[ -n "$terminfo[knp]"   ]] && key[PageDown]=$terminfo[knp]
[[ -n "$terminfo[kcuu1]" ]] && key[Up]=$terminfo[kcuu1]
[[ -n "$terminfo[kcub1]" ]] && key[Left]=$terminfo[kcub1]
[[ -n "$terminfo[kcud1]" ]] && key[Down]=$terminfo[kcud1]
[[ -n "$terminfo[kcuf1]" ]] && key[Right]=$terminfo[kcuf1]

# Default key bindings

[[ -n "${key[Home]}"      ]] && bindkey -- "${key[Home]}"       beginning-of-line
[[ -n "${key[End]}"       ]] && bindkey -- "${key[End]}"        end-of-line
[[ -n "${key[Insert]}"    ]] && bindkey -- "${key[Insert]}"     overwrite-mode
[[ -n "${key[Backspace]}" ]] && bindkey -- "${key[Backspace]}"  backward-delete-char
[[ -n "${key[Delete]}"    ]] && bindkey -- "${key[Delete]}"     delete-char
[[ -n "${key[Up]}"        ]] && bindkey -- "${key[Up]}"         up-line-or-history
[[ -n "${key[Down]}"      ]] && bindkey -- "${key[Down]}"       down-line-or-history
[[ -n "${key[Left]}"      ]] && bindkey -- "${key[Left]}"       backward-char
[[ -n "${key[Right]}"     ]] && bindkey -- "${key[Right]}"      forward-char
[[ -n "${key[PageUp]}"    ]] && bindkey -- "${key[PageUp]}"     beginning-of-buffer-or-history
[[ -n "${key[PageDown]}"  ]] && bindkey -- "${key[PageDown]}"   end-of-buffer-or-history
[[ -n "${key[Shift-Tab]}" ]] && bindkey -- "${key[Shift-Tab]}"  reverse-menu-complete

# Default prompt
PS1="%n@%m %1~ %# "

# Finally, make sure the terminal is in application mode, when zle is
# active. Only then are the values from $terminfo valid.
if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
    autoload -Uz add-zle-hook-widget
    function zle_application_mode_start { echoti smkx }
    function zle_application_mode_stop { echoti rmkx }
    add-zle-hook-widget -Uz zle-line-init zle_application_mode_start
    add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop
fi

autoload -U compinit && compinit
_comp_options+=(globdots)

alias grep="grep --color=auto --exclude-dir={.git,.svn}"
alias ip='ip -color=auto'
alias ls="ls -hpv --color=auto --group-directories-first"
zle_highlight=('paste:none')

[[ -d $HOME/.local/bin && ! $PATH =~ $HOME/.local/bin ]] &&
    export PATH=$HOME/.local/bin:$PATH
EOF