# # Source at https://github.com/nivertius/zsh-rc/ # Download Powerline-patched fonts from # https://github.com/powerline/fonts # #---------------------------------- Configuration ----------------------------- DEFAULT_USER="nivertius" EDITOR="vim" #---------------------------------- Pre Setup --------------------------------- autoload colors; colors autoload -Uz add-zsh-hook LAST_RETURN_VALUE=0 # Characters UNSTAGED_CHARACTER="\u26a1" CHANGES_CHARACTER="\u00b1" BRANCH_CHARACTER="\ue0a0" DETACHED_CHARACTER="\u27a6" REVISION_CHARACTER="\u2022" FAILED_CHARACTER="\u2718" SUCCESS_CHARACTER="\u2714" SUPERUSER_CHARACTER="\u26a1" JOBS_CHARACTER="\u2699" NO_JOBS_CHARACTER="\u2022" #---------------------------------- Helpers ----------------------------------- # Search file up in directory tree. Either print path to found file or nothing find_up () { path=$(pwd) while [[ "$path" != "" ]]; do if [[ -e "$path/$1" ]]; then echo "$path/$1" return; fi path=${path%/*} done } #---------------------------------- Tab completion ---------------------------- autoload -Uz compinit compinit # Force a reload of completion system if nothing matched; this fixes installing # a program and then trying to tab-complete its name _force_rehash() { (( CURRENT == 1 )) && rehash return 1 # Because we didn't really complete anything } # Always use menu completion, and make the colors pretty! zstyle ':completion:*' menu select yes zstyle ':completion:*:default' list-colors '' # Completers to use: rehash, general completion, then various magic stuff and # spell-checking. Only allow two errors when correcting zstyle ':completion:*' completer _force_rehash _complete _ignored _match _correct _approximate _prefix zstyle ':completion:*' max-errors 2 # When looking for matches, first try exact matches, then case-insensiive, then partial word completion zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' 'r:|[._-]=** r:|=**' # Turn on caching, which helps with e.g. apt zstyle ':completion:*' use-cache on zstyle ':completion:*' cache-path "$HOME/.zsh/cache" mkdir -p $HOME/.zsh/cache # Show nice warning when nothing matched zstyle ':completion:*:warnings' format '%No matches: %d%b' # Show titles for completion types and group by type zstyle ':completion:*:descriptions' format "%U%B%F{yellow}ยป %d%u%b%f" zstyle ':completion:*' group-name '' # Ignore some common useless files zstyle ':completion:*' ignored-patterns '*?.pyc' '__pycache__' zstyle ':completion:*:*:rm:*:*' ignored-patterns # Directories zstyle ':completion:*:default' list-colors "${(s.:.)LS_COLORS}" zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories zstyle ':completion:*:*:cd:*:directory-stack' menu yes select zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand' zstyle ':completion:*' squeeze-slashes true # kill: advanced kill completion zstyle ':completion::*:kill:*:*' command 'ps xf -U $USER -o pid,%cpu,cmd' zstyle ':completion::*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;32' # sudo completion zstyle ':completion:*:sudo:*' command-path append /sbin /usr/sbin list-ssh-hosts() { [[ -f $HOME/.ssh/config ]] && print -n $(cat $HOME/.ssh/config | sed '/^Host /!d;s/Host *\([^ \#]\+\)/\1/') } zstyle ':completion:*:ssh:*' hosts $(list-ssh-hosts) zstyle ':completion:*:scp:*' hosts $(list-ssh-hosts) zstyle ':completion:*:ssh:*' users # disables users completion zstyle ':completion:*:scp:*' users # disables users completion zstyle :compinstall filename "$HOME/.zshrc" # Always do mid-word tab completion setopt complete_in_word #---------------------------------- Corrections ------------------------------- # dont correct arguments to dot-files CORRECT_IGNORE='[._]*' CORRECT_IGNORE_FILE='[._]*' #---------------------------------- Prediction -------------------------------- autoload predict-on autoload predict-off zle -N predict-on zle -N predict-off bindkey "^Z" predict-on # C-z bindkey "^X^Z" predict-off # C-x C-z #---------------------------------- History ----------------------------------- setopt append_history # Allow multiple terminal sessions to all append to one zsh command history setopt extended_history # save timestamp of command and duration setopt inc_append_history # Add comamnds as they are typed, don't wait until shell exit setopt hist_expire_dups_first # when trimming history, lose oldest duplicates first setopt hist_ignore_dups # Do not write events to history that are duplicates of previous events setopt hist_ignore_space # remove command line from history list when first character on the line is a space setopt hist_find_no_dups # When searching history don't display results already cycled through twice setopt hist_reduce_blanks # Remove extra blanks from each command line being added to history setopt hist_verify # don't execute, just expand history setopt share_history # imports new commands and appends typed commands to history setopt hist_no_store # remove the history (fc -l) command from the history when invoked. export HISTFILE=~/.zsh_history export HISTSIZE=1000000 export SAVEHIST=1000000 #---------------------------------- Prompt ------------------------------------ # Based on agnoster's Theme - https://gist.github.com/3712874 CURRENT_BG='NONE' # Characters SEGMENT_SEPARATOR_FORWARD="\ue0b0" SEGMENT_SEPARATOR_BACKWARD="\ue0b2" prompt_segment() { local direction newbg newfg text direction="$1" newbg="$2" newfg="$3" text="$4" if [[ -z $text ]]; then return; fi if [[ $newbg != $CURRENT_BG ]]; then if [[ "$direction" == 'forward' ]]; then if [[ $CURRENT_BG != 'NONE' ]]; then print -n "%{%K{$newbg}%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR_FORWARD%{%F{$newfg}%}" else print -n "%{%K{$newbg}%F{$newfg}%}" fi else print -n "%{%F{$newbg}%}$SEGMENT_SEPARATOR_BACKWARD%{%F{$newfg}%K{$newbg}%}" fi fi print -n " $text " CURRENT_BG=$newbg } # End the prompt, closing any open segments prompt_end() { if [[ -n $CURRENT_BG ]]; then print -n "%{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR_FORWARD" fi CURRENT_BG='' } prompt_clear() { print -n "%{%k%f%}" CURRENT_BG='' } ### Prompt components # Each component will draw itself, and hide itself if no information needs to be shown # Root privileges prompt_root() { if [[ $UID -eq 0 ]]; then print -n $SUPERUSER_CHARACTER fi } # Different username prompt_user() { local user=$(whoami) if [[ "$user" != "$DEFAULT_USER" && $UID -ne 0 ]]; then print -n $user fi } # Different host prompt_host() { if [[ -n "$SSH_CONNECTION" ]]; then print -n "%m" fi } # Status: # - was there an error # - are there background jobs? prompt_status() { local symbols symbols=() if [[ $LAST_RETURN_VALUE -ne 0 ]]; then symbols+="%{%F{red}%}$FAILED_CHARACTER%{%f%}" else symbols+="%{%F{green}%}$SUCCESS_CHARACTER%{%f%}" fi if [[ $(jobs -l | wc -l) -gt 0 ]]; then symbols+="%{%F{cyan}%}$JOBS_CHARACTER%{%f%}" else symbols+="%{%F{white}%}$NO_JOBS_CHARACTER%{%f%}" fi echo "$symbols" } ## Main prompt prompt_forward() { CURRENT_BG='NONE' prompt_segment forward black default "$(prompt_status)" prompt_segment forward red yellow "$(prompt_root)" prompt_segment forward magenta black "$(prompt_user)" prompt_segment forward cyan black "$(prompt_host)" prompt_segment forward blue black '%~' # prompt directory prompt_end prompt_clear } ## Reverse prompt prompt_backward() { CURRENT_BG='NONE' prompt_segment backward magenta black "$MAVEN_PROJECT" # prompt maven project prompt_segment backward yellow black "$vcs_info_msg_0_" # prompt vcs prompt_segment backward green black "%T" # prompt time prompt_clear } prompt_precmd() { vcs_info PROMPT="%{%f%b%k%}$(prompt_forward) " RPROMPT="%{%f%b%k%}$(prompt_backward)" } ZLE_RPROMPT_INDENT=0 prompt_opts=(cr subst percent) add-zsh-hook precmd prompt_precmd #---------------------------------- VCS --------------------------------------- autoload -Uz vcs_info zstyle ':vcs_info:*' enable git hg svn zstyle ':vcs_info:*' check-for-changes true zstyle ':vcs_info:*' get-revision true # these formats are set for PROMPT zstyle ':vcs_info:*' formats "%s $BRANCH_CHARACTER%b $REVISION_CHARACTER%i%u" zstyle ':vcs_info:*' actionformats "%s $BRANCH_CHARACTER%b $REVISION_CHARACTER%i%u [%a]" zstyle ':vcs_info:*' branchformat '%b' zstyle ':vcs_info:hg*' unstagedstr "$CHANGES_CHARACTER" zstyle ':vcs_info:hg*' hgrevformat "%r" # default "%r:%h" zstyle ':vcs_info:git*' formats "%s $BRANCH_CHARACTER%b%u" zstyle ':vcs_info:git*' actionformats "%s $BRANCH_CHARACTER%b%u [%a]" zstyle ':vcs_info:git*' unstagedstr "$UNSTAGED_CHARACTER" zstyle ':vcs_info:git*' stagedstr "$CHANGES_CHARACTER" #---------------------------------- Listings ---------------------------------- LSOPTS='-lAvF' # long mode, show all, natural sort, type squiggles, friendly sizes LLOPTS='' case $(uname -s) in FreeBSD) LSOPTS="${LSOPTS} -G" ;; Linux) eval "$(dircolors -b)" LSOPTS="$LSOPTS --color=auto" LLOPTS="$LLOPTS --color=always" # so | less is colored # Just loaded new ls colors via dircolors, so change completion colors # to match zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} ;; esac alias ls="ls $LSOPTS" alias ll="ls $LLOPTS | less -FX" #---------------------------------- Screen ------------------------------------ function title { # param: title to use local prefix='' # If I'm in a screen, all the windows are probably on the same machine, so # I don't really need to title every single one with the machine name. # On the other hand, if I'm not logged in as me (but, e.g., root), I'd # certainly like to know that! if [[ $USER != "$DEFAULT_USER" ]]; then prefix="[$USER] " fi # Set screen window title if [[ $TERM == "screen"* ]]; then print -n "\ek$prefix$1\e\\" fi # Prefix the xterm title with the current machine name, but only if I'm not # on a local machine. This is tricky, because screen won't reliably know # whether I'm using SSH right now! So just assume I'm local iff I'm not # running over SSH *and* not using screen. Local screens are fairly rare. prefix=$HOST if [[ $SSH_CONNECTION == '' && $TERM != "screen"* ]]; then prefix='' fi # If we're showing host and not default user prepend it if [[ $prefix != '' && $USER != "$DEFAULT_USER" ]]; then prefix="$USER@$prefix" fi # Wrap it in brackets if [[ $prefix != '' ]]; then prefix="[$prefix] " fi # Set xterm window title if [[ $TERM == "xterm"* || $TERM == "screen"* ]]; then print -n "\e]2;$prefix$1\a" fi } function title_precmd { # Shorten homedir back to '~' local shortpwd=${PWD/$HOME/\~} title "zsh $shortpwd" } function title_preexec { title $* } add-zsh-hook preexec title_preexec add-zsh-hook precmd title_precmd #---------------------------------- Bindings ---------------------------------- bindkey -v # General movement # Taken from http://wiki.archlinux.org/index.php/Zsh and Ubuntu's inputrc 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[1;5C" forward-word bindkey "\e[1;5D" backward-word 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 ' ' magic-space # do history expansion on space # 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 # Tab completion bindkey "^r" history-incremental-search-backward bindkey '^i' complete-word # tab to do menu bindkey "\e[Z" reverse-menu-complete # shift-tab to reverse menu # Up/down arrow. # I want shared history for ^R, but I don't want another shell's activity to # mess with up/down. This does that. down-line-or-local-history() { zle set-local-history 1 zle down-line-or-history zle set-local-history 0 } zle -N down-line-or-local-history up-line-or-local-history() { zle set-local-history 1 zle up-line-or-history zle set-local-history 0 } zle -N up-line-or-local-history bindkey "\e[A" up-line-or-local-history bindkey "\e[B" down-line-or-local-history #---------------------------------- Aliases ---------------------------------- # Use interactive sudo instead of su alias su="sudo -u root -i" # disable sudo correction for commands alias sudo="nocorrect sudo" #---------------------------------- Maven ------------------------------------ # Coloring maven output # based on https://gist.github.com/katta/1027800 mvn-color() { mvn $@ 2>/dev/null | sed -e " /^\W*$/d s/\(-\{20,\}\)/$fg[black]\1$reset_color/g s/Building \(.*\)/Building $fg_bold[magenta]\1$reset_color/g s/--- \([^@]\+\) @ \(.*\) ---/$fg_bold[magenta]\2$reset_color - $fg_bold[cyan]\1$reset_color ---/g s/\(\(BUILD \)\?SUCCESS\)/$fg_bold[green]\1$reset_color/g s/\(\(BUILD \)\?FAILURE\)/$fg_bold[red]\1$reset_color/g s/\(SKIPPED\)/$fg_bold[yellow]\1$reset_color/g s/\(\[INFO\]\)\(.*\)/$fg_bold[blue]---$reset_color\2/g s/\(\[WARNING\]\)\(.*\)/$fg_bold[yellow]>>>$reset_color\2/g s/\(\[ERROR\]\)\(.*\)/$fg_bold[red]!!!$reset_color\2/g s/^ T E S T S/$fg_bold[blue]~~~$reset_color / s/Results :/$fg_bold[blue]~~~$reset_color Total: / s/Running \([a-zA-Z0-9.]\+\)/$fg_bold[blue]~~~$reset_color Test: $fg_bold[cyan]\1$reset_color/ s/Tests run: \([^,]*\), Failures: \([^,]*\), Errors: \([^,]*\), Skipped: \([^,]*\)/$fg_bold[blue]~~~$reset_color Run: $fg_bold[green]\1$reset_color, Failed: $fg_bold[red]\2$reset_color, Error: $fg_bold[red]\3$reset_color, Skipped: $fg_bold[yellow]\4$reset_color/ " echo -ne "$reset_color" } alias mvn='mvn-color' # Read project information from current directory - needed for prompt maven_read_project() { local location parts location=$(find_up pom.xml) if [[ ! -r "$location" || -z $commands[xmllint] ]]; then MAVEN_PROJECT="" return 1; fi # executing xmllint takes some time, so this does it in single execution parts=($(echo "cat /*[local-name()='project']/*[local-name()='artifactId']/text()\n" \ "cat /*[local-name()='project']/*[local-name()='version']/text()\n" \ "cat /*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']/text()\n" | \ xmllint --shell $location 2>/dev/null | \ sed '/^\/ >/d' | \ sed '/^ -------/d')) if [[ "${#parts}" > 1 ]]; then MAVEN_PROJECT="${parts[1]}@${parts[2]}" else MAVEN_PROJECT="pom!" fi; } add-zsh-hook chpwd maven_read_project #---------------------------------- Copy zshrc remote ------------------------- sshc() { local source target source=${ZDOTDIR:-$HOME} target="/tmp/.zdot-${RANDOM}" ssh -q -o "ControlPath=/tmp/.cm-%r@%h:%p" -o "ControlMaster=yes" -o "ControlPersist=yes" $1 'false' ssh -q -o "ControlPath=/tmp/.cm-%r@%h:%p" $1 "mkdir $target" scp -q -o "ControlPath=/tmp/.cm-%r@%h:%p" $source/.zshrc $1:$target/.zshrc ssh -q -o "ControlPath=/tmp/.cm-%r@%h:%p" $1 -t "ZDOTDIR=$target exec zsh -l" ssh -q -o "ControlPath=/tmp/.cm-%r@%h:%p" $1 "rm -r $target" ssh -q -o "ControlPath=/tmp/.cm-%r@%h:%p" -O stop $1 } compdef '_dispatch ssh ssh' sshc #---------------------------------- Miscellaneous ---------------------------- setopt extended_glob setopt correct # try to correct the spelling of commands. setopt correct_all # try to correct the spelling of all arguments in a line. setopt numeric_glob_sort # if numeric filenames are matched by a filename generation pattern, sort the filenames numerically rather than lexicographically. setopt nomatch # if there is match on file pattern, dont run command (instead of running command with unchanged parameters) setopt interactive_comments # allow comments in command line setopt multios # enable multiple input/output redirections that work as expected unsetopt beep # (dont) beep on errors unsetopt notify # (dont) report the status of background jobs immediately, rather than waiting until just before printing a prompt. unsetopt auto_cd # (dont) enter the directory that was inputed as command unsetopt auto_remove_slash # (dont) remove last slash when next character is delimiter unsetopt csh_junkie_quotes # (dont) complain if a quoted expression runs off the end of a line; prevent quoted expressions from containing un-escaped newlines. # Don't count common path separators as word characters WORDCHARS=${WORDCHARS//[&.;\/]} # Report time if command takes too long REPORTTIME=5 TIMEFMT=$(echo "$fg[green]${SEGMENT_SEPARATOR_BACKWARD}$bg[green]$fg[black] %*Es $fg[yellow]$SEGMENT_SEPARATOR_BACKWARD$bg[yellow]$fg[black] %P $reset_color") # Don't glob with find or wget for command in find wget; \ alias $command="noglob $command" # load zsh extended move autoload -Uz zmv #---------------------------------- Post Setup -------------------------------- store_last_return_value() { LAST_RETURN_VALUE="$?" } # Store last return value into separate variable # This must be exactly first precmd function, because other precmd might modify $? precmd_functions=(store_last_return_value $precmd_functions) #---------------------------------- Machine specific -------------------------- if [[ -r $HOME/.zlocal ]]; then source $HOME/.zlocal fi