/etc/zsh/zshrc: support displaying version control information inside prompt
[grml-etc-core.git] / etc / zsh / zshrc
index 33b60ea..47dfa2e 100644 (file)
@@ -3,7 +3,7 @@
 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
 # Bug-Reports:   see http://grml.org/bugs/
 # License:       This file is licensed under the GPL v2.
-# Latest change: Mon Jul 02 18:17:08 CEST 2007 [mika]
+# Latest change: Don Okt 18 10:22:10 CEST 2007 [mika]
 ################################################################################
 # This file is sourced only for interactive shells. It
 # should contain commands to set up aliases, functions,
@@ -11,8 +11,8 @@
 #
 # Global Order: zshenv, zprofile, zshrc, zlogin
 ################################################################################
-#
-# zsh-refcard-tag documentation:
+
+# zsh-refcard-tag documentation: {{{
 #   You may notice strange looking comments in the zshrc (and ~/.zshrc as
 #   well). These are there for a purpose. grml's zsh-refcard can now be
 #   automatically generated from the contents of the actual configuration
@@ -20,7 +20,7 @@
 #   and what lines of code to take into account (and for what purpose).
 #
 # Here is what they mean:
-#{{{
+#
 # List of tags (comment types) used:
 #   #a#     Next line contains an important alias, that should
 #           be included in the grml-zsh-refcard.
   #f1# Checks whether or not you're running grml-small
     isgrmlsmall() {
     [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
-  }
+    }
   else
     isgrmlsmall() { return 1 }
   fi
   export MAIL=${MAIL:-/var/mail/$USER}
   # if we don't set $SHELL then aterm, rxvt,.. will use /bin/sh or /bin/bash :-/
   export SHELL='/bin/zsh'
-  [[ -f ~/.terminfo/m/mostlike ]] && MYLESS='LESS=C TERMINFO=~/.terminfo TERM=mostlike less' || MYLESS='less'
   [ -x $(which dircolors) ] && eval `dircolors -b`
 
 # Search path for the cd command
@@ -509,10 +508,11 @@ fi
 #  zle -N mquote && bindkey '^q' mquote
 
 # run command line as user root via sudo:
-  _sudo-command-line() {
-    [[ $BUFFER != sudo\ * ]] && LBUFFER="sudo $LBUFFER"
+  sudo-command-line() {
+    [[ -z $BUFFER ]] && zle up-history
+    [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
   }
-  zle -N sudo-command-line _sudo-command-line
+  zle -N sudo-command-line
 #k# Put the current command line into a \kbd{sudo} call
   bindkey "^Os" sudo-command-line
 
@@ -567,6 +567,7 @@ fi
   setopt auto_pushd           # make cd push the old directory onto the directory stack.
   setopt nonomatch            # try to avoid the 'zsh: no matches found...'
   setopt nobeep               # avoid "beep"ing
+  setopt pushd_ignore_dups    # don't push the same dir twice.
 
   MAILCHECK=30       # mailchecks
   REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 seconds
@@ -601,7 +602,7 @@ fi
 # dirstack handling {{{
   DIRSTACKSIZE=20
   if [[ -f ~/.zdirs ]] && [[ ${#dirstack[*]} -eq 0 ]]; then
-     dirstack=( ${(uf)"$(< ~/.zdirs)"} )
+     dirstack=( ${(f)"$(< ~/.zdirs)"} )
      # "cd -" won't work after login by just setting $OLDPWD, so
      [[ -d $dirstack[0] ]] && cd $dirstack[0] && cd $OLDPWD
   fi
@@ -622,6 +623,67 @@ fi
   fi
 # }}}
 
+# display version control information on right side of prompt if $VCS is set {{{
+# based on Mike Hommey's http://web.glandium.org/blog/?p=170
+  __vcs_dir() {
+    local vcs base_dir sub_dir ref
+    sub_dir() {
+      local sub_dir
+      sub_dir=$(readlink -f "${PWD}")
+      sub_dir=${sub_dir#$1}
+      echo ${sub_dir#/}
+    }
+
+    git_dir() {
+      base_dir=$(git-rev-parse --show-cdup 2>/dev/null) || return 1
+      base_dir=$(readlink -f "$base_dir/..")
+      sub_dir=$(git-rev-parse --show-prefix)
+      sub_dir=${sub_dir%/}
+      ref=$(git-symbolic-ref -q HEAD || git-name-rev --name-only HEAD 2>/dev/null)
+      ref=${ref#refs/heads/}
+      vcs="git"
+    }
+
+    svn_dir() {
+      [ -d ".svn" ] || return 1
+      base_dir="."
+      while [ -d "$base_dir/../.svn" ]; do base_dir="$base_dir/.."; done
+      base_dir=$(readlink -f "$base_dir")
+      sub_dir=$(sub_dir "${base_dir}")
+      ref=$(svn info "$base_dir" | awk '/^URL/ { sub(".*/","",$0); r=$0 } /^Revision/ { sub("[^0-9]*","",$0); print r":"$0 }')
+      vcs="svn"
+    }
+
+    svk_dir() {
+      [ -f ~/.svk/config ] || return 1
+      base_dir=$(awk '/: *$/ { sub(/^ */,"",$0); sub(/: *$/,"",$0); if (match("'${PWD}'", $0"(/|$)")) { print $0; d=1; } } /depotpath/ && d == 1 { sub(".*/","",$0); r=$0 } /revision/ && d == 1 { print r ":" $2; exit 1 }' ~/.svk/config) && return 1
+      ref=${base_dir##*
+  }
+      base_dir=${base_dir%%
+  *}
+      sub_dir=$(sub_dir "${base_dir}")
+      vcs="svk"
+    }
+
+    hg_dir() {
+      base_dir="."
+      while [ ! -d "$base_dir/.hg" ]; do base_dir="$base_dir/.."; [ $(readlink -f "${base_dir}") = "/" ] && return 1; done
+      base_dir=$(readlink -f "$base_dir")
+      sub_dir=$(sub_dir "${base_dir}")
+      ref=$(< "${base_dir}/.hg/branch")
+      vcs="hg"
+    }
+
+    hg_dir  ||
+    git_dir ||
+    svn_dir ||
+    svk_dir # ||
+  #  base_dir="$PWD"
+  #  echo "${vcs:+($vcs)}${base_dir/$HOME/~}${vcs:+[$ref]${sub_dir}}"
+    echo "${vcs:+($vcs)}${base_dir}${vcs:+[$ref]${sub_dir}}"
+  }
+# }}}
+
 # {{{ set prompt
   if autoload promptinit && promptinit 2>/dev/null ; then
      promptinit # people should be able to use their favourite prompt
@@ -629,6 +691,7 @@ fi
      print 'Notice: no promptinit available :('
   fi
 
+
 # precmd() => a function which is executed just before each prompt
 # use 'NOPRECMD=1' to disable the precmd + preexec commands
 
@@ -642,13 +705,15 @@ fi
       # allow manual overwriting of RPROMPT
       if [[ -n $RPROMPT ]] ; then
          [[ $TERM == screen* ]] && echo -n $'\ekzsh\e\\'
-         return 0
+         return 0
       fi
       # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
       if [[ -z $DONTSETRPROMPT ]] ; then
          if [[ -n $BATTERY ]] ; then
             RPROMPT="%(?..:()% ${PERCENT}${SCREENTITLE}"
             # RPROMPT="${PERCENT}${SCREENTITLE}"
+         elif [[ -n $VCS ]] ; then
+            RPROMPT="%(?..:()% $(__vcs_dir)${SCREENTITLE}"
          else
             RPROMPT="%(?..:()% ${SCREENTITLE}"
             # RPROMPT="${SCREENTITLE}"
@@ -808,16 +873,25 @@ ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
   alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
   alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
 
-  alias utf2iso='if isutfenv ; then
-   for ENV in `env | grep UTF` ; do
-       eval export "$(echo $ENV | sed 's/UTF-8/iso885915/')"
-   done
-   fi'
-  alias iso2utf='if isutfenv ; then
-   for ENV in `env | grep '\.iso'` ; do
-       eval export "$(echo $ENV | sed 's/iso.*/UTF-8/')"
-   done
-   fi'
+  # make sure it is not assigned yet
+  [[ $(whence -w utf2iso &>/dev/null) == 'utf2iso: alias' ]] && unalias utf2iso
+  utf2iso() {
+    if isutfenv ; then
+       for ENV in $(env | command grep -i '.utf') ; do
+           eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
+       done
+     fi
+  }
+
+  # make sure it is not assigned yet
+  [[ $(whence -w iso2utf &>/dev/null) == 'iso2utf: alias' ]] && unalias iso2utf
+  iso2utf() {
+   if ! isutfenv ; then
+      for ENV in $(env | command grep -i '\.iso') ; do
+          eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
+      done
+   fi
+ }
 
 # set up software synthesizer via speakup
   alias swspeak='
@@ -838,6 +912,13 @@ ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
 # I like clean prompt, so provide simple way to get that
   alias 0 &>/dev/null || functions 0 &>/dev/null || alias 0='return 0'
 
+# for really lazy people like mika:
+  type S &>/dev/null || alias S='screen'
+  type s &>/dev/null || alias s='ssh'
+
+# get top 10 shell commands:
+  alias top10='print -l ? ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
+
 # truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i'
   if [ -x $(which truecrypt) ] ; then
      if isutfenv ; then
@@ -915,8 +996,8 @@ Enjoy your grml system with the zsh!$reset_color"
     salias ag="apt-get upgrade"
     #a3# Execute \kbd{apt-get update}
     salias au="apt-get update"
-    #a3# Execute \kbd{aptitude update ; aptitude upgrade}
-    salias -a up="aptitude update ; aptitude upgrade"
+    #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
+    salias -a up="aptitude update ; aptitude safe-upgrade"
     #a3# Execute \kbd{dpkg-buildpackage}
     alias dbp='dpkg-buildpackage'
     #a3# Execute \kbd{grep-excuses}
@@ -1010,7 +1091,7 @@ Run "grml-tips ssl-certificate" if you need further instructions.
 grmlcomp() {
 ## completion system
   zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )' # allow one error for every three characters typed in approximate completer
-  zstyle ':completion:*:complete:-command-::commands' ignored-patterns '*\~' # don't complete backup files as executables
+  zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)' # don't complete backup files as executables
   zstyle ':completion:*:correct:*'       insert-unambiguous true             # start menu completion only if it could find no unambiguous initial string
   zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}' #
   zstyle ':completion:*:correct:*'       original true                       #
@@ -1054,20 +1135,20 @@ grmlcomp() {
     }
 # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
   if [[ -n "$NOCOR" ]] ; then
-    zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files
+    zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
     setopt nocorrect # do not try to correct the spelling if possible
   else
-#    zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _correct _approximate _files
+#    zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _ignored _correct _approximate _files
     setopt correct  # try to correct the spelling if possible
     zstyle -e ':completion:*' completer '
         if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]]; then
           _last_try="$HISTNO$BUFFER$CURSOR"
-          reply=(_complete _match _prefix _files)
+          reply=(_complete _match _ignored _prefix _files)
         else
           if [[ $words[1] = (rm|mv) ]]; then
             reply=(_complete _files)
           else
-            reply=(_oldlist _expand _force_rehash _complete _correct _approximate _files)
+            reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
           fi
         fi'
   fi
@@ -1145,7 +1226,7 @@ grmlstuff() {
 # people should use 'grml-x'!
   startx() {
     if [ -e /etc/X11/xorg.conf ] ; then
-       [ -x /usr/bin/startx ] && /usr/bin/startx || /usr/X11R6/bin/startx
+       [ -x /usr/bin/startx ] && /usr/bin/startx "$@" || /usr/X11R6/bin/startx "$@"
     else
       echo "Please use the script \"grml-x\" for starting the X Window System
 because there does not exist /etc/X11/xorg.conf yet.
@@ -1247,6 +1328,7 @@ If you want to use xinit anyway please call \"/usr/bin/xinit\"."
   else
      manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
      # manzsh()  { /usr/bin/man zshall |  most +/"$1" ; }
+     # [[ -f ~/.terminfo/m/mostlike ]] && MYLESS='LESS=C TERMINFO=~/.terminfo TERM=mostlike less' || MYLESS='less'
      # manzsh()  { man zshall | $MYLESS -p $1 ; }
   fi
 
@@ -1255,11 +1337,13 @@ If you want to use xinit anyway please call \"/usr/bin/xinit\"."
     dchange() {
       if [ -r /usr/share/doc/${1}/changelog.Debian.gz ] ; then
          most /usr/share/doc/${1}/changelog.Debian.gz
+      elif [ -r /usr/share/doc/${1}/changelog.gz ] ; then
+         most /usr/share/doc/${1}/changelog.gz
       else
          if type -p aptitude &>/dev/null ; then
             echo "No changelog for package $1 found, using aptitude to retrieve it."
             if isgrml ; then
-              aptitude -t unstable changelog tsclient
+              aptitude -t unstable changelog ${1}
             else
               aptitude changelog ${1}
             fi
@@ -1484,6 +1568,11 @@ If you want to use xinit anyway please call \"/usr/bin/xinit\"."
     exec env -i ENV="/etc/minimal-shellrc" HOME="$HOME" TERM="$TERM" ksh
   }
 
+  # make a backup of a file
+  bk() {
+    cp -a "$1" "${1}_$(date --iso-8601=seconds)"
+  }
+
   # Switching shell safely and efficiently? http://www.zsh.org/mla/workers/2001/msg02410.html
   # bash() {
   #  NO_SWITCH="yes" command bash "$@"