zshrc: Add function to toggle colour codes in vcs_info formats
[grml-etc-core.git] / etc / zsh / zshrc
index c01dac7..6533d72 100644 (file)
@@ -406,6 +406,7 @@ check_com() {
 salias() {
     emulate -L zsh
     local only=0 ; local multi=0
+    local key val
     while [[ $1 == -* ]] ; do
         case $1 in
             (-o) only=1 ;;
@@ -495,11 +496,7 @@ xcat() {
 xunfunction() {
     emulate -L zsh
     local -a funcs
-    funcs=(salias xcat xsource xunfunction zrcautoload
-                                           zrcautozle
-                                           zrcbindkey
-                                           zrcgotkeymap
-                                           zrcgotwidget)
+    funcs=(salias xcat xsource xunfunction zrcautoload zrcautozle)
     for func in $funcs ; do
         [[ -n ${functions[$func]} ]] \
             && unfunction $func
@@ -524,10 +521,6 @@ for var in LANG LC_ALL LC_MESSAGES ; do
     [[ -n ${(P)var} ]] && export $var
 done
 
-xsource "/etc/sysconfig/keyboard"
-
-TZ=$(xcat /etc/timezone)
-
 # set some variables
 if check_com -c vim ; then
 #v#
@@ -543,7 +536,12 @@ export PAGER=${PAGER:-less}
 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'
+if [[ -z "$SHELL" ]] ; then
+  SHELL="$(which zsh)"
+  if [[ -x "$SHELL" ]] ; then
+    export SHELL
+  fi
+fi
 
 # color setup for ls:
 check_com -c dircolors && eval $(dircolors -b)
@@ -596,7 +594,7 @@ typeset -U path cdpath fpath manpath
 
 # Load a few modules
 is4 && \
-for mod in complist deltochar mathfunc ; do
+for mod in parameter complist deltochar mathfunc ; do
     zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
 done
 
@@ -608,8 +606,9 @@ if is4 ; then
 fi
 
 # completion system
+COMPDUMPFILE=${COMPDUMPFILE:-${ZDOTDIR:-${HOME}}/.zcompdump}
 if zrcautoload compinit ; then
-    compinit || print 'Notice: no compinit available :('
+    compinit -d ${COMPDUMPFILE} || print 'Notice: no compinit available :('
 else
     print 'Notice: no compinit available :('
     function compdef { }
@@ -776,7 +775,7 @@ grmlcomp() {
 
     # use generic completion system for programs not yet defined; (_gnu_generic works
     # with commands that provide a --help option with "standard" gnu-like output.)
-    for compcom in cp deborphan df feh fetchipac head hnb ipacsum mv \
+    for compcom in cp deborphan df feh fetchipac gpasswd head hnb ipacsum mv \
                    pal stow tail uname ; do
         [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
     done; unset compcom
@@ -785,11 +784,11 @@ grmlcomp() {
     compdef _hosts upgrade
 }
 
-# Keyboard setup: The following is the same code, we wrote for debian's setup.
-# It ensures the terminal is in the right mode, when zle is active, so the
-# values from $terminfo are valid. Therefore, this setup should work on all
-# systems, that have support for `terminfo'. It also requires the zsh in use to
-# have the `zsh/terminfo' module built.
+# Keyboard setup: The following is based on the same code, we wrote for
+# debian's setup. It ensures the terminal is in the right mode, when zle is
+# active, so the values from $terminfo are valid. Therefore, this setup should
+# work on all systems, that have support for `terminfo'. It also requires the
+# zsh in use to have the `zsh/terminfo' module built.
 #
 # If you are customising your `zle-line-init()' or `zle-line-finish()'
 # functions, make sure you call the following utility functions in there:
@@ -819,21 +818,6 @@ beginning-or-end-of-somewhere() {
 zle -N beginning-of-somewhere beginning-or-end-of-somewhere
 zle -N end-of-somewhere beginning-or-end-of-somewhere
 
-## toggle the ,. abbreviation feature on/off
-# NOABBREVIATION: default abbreviation-state
-#                 0 - enabled (default)
-#                 1 - disabled
-NOABBREVIATION=${NOABBREVIATION:-0}
-
-grml_toggle_abbrev() {
-    if (( ${NOABBREVIATION} > 0 )) ; then
-        NOABBREVIATION=0
-    else
-        NOABBREVIATION=1
-    fi
-}
-zle -N grml_toggle_abbrev
-
 # add a command line to the shells history without executing it
 commit-to-history() {
     print -s ${(z)BUFFER}
@@ -995,11 +979,10 @@ zle -N accept-line
 zle -N Accept-Line
 zle -N Accept-Line-HandleContext
 
-# power completion - abbreviation expansion
 # power completion / abbreviation expansion / buffer expansion
 # see http://zshwiki.org/home/examples/zleiab for details
 # less risky than the global aliases but powerful as well
-# just type the abbreviation key and afterwards ',.' to expand it
+# just type the abbreviation key and afterwards 'ctrl-x .' to expand it
 declare -A abk
 setopt extendedglob
 setopt interactivecomments
@@ -1031,24 +1014,18 @@ zleiab() {
     setopt extendedglob
     local MATCH
 
-    if (( NOABBREVIATION > 0 )) ; then
-        LBUFFER="${LBUFFER},."
-        return 0
-    fi
-
     LBUFFER=${LBUFFER%%(#m)[.\-+:|_a-zA-Z0-9]#}
     LBUFFER+=${abk[$MATCH]:-$MATCH}
 }
 
-zle -N zleiab && bindkey ",." zleiab ## KEYB!
+zle -N zleiab
 
 help-show-abk()
 {
-  zle -M "$(print "Type ,. after these abbreviations to expand them:"; print -a -C 2 ${(kv)abk})"
+  zle -M "$(print "Available abbreviations for expansion:"; print -a -C 2 ${(kv)abk})"
 }
 
-#k# Display list of abbreviations that expand when followed by ,.
-zle -N help-show-abk && bindkey '^xb' help-show-abk ## KEYB!
+zle -N help-show-abk
 
 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
 insert-datestamp() { LBUFFER+=${(%):-'%D{%Y-%m-%d}'}; }
@@ -1127,8 +1104,7 @@ inplaceMkDirs() {
     fi
 }
 
-#k# mkdir -p <dir> from string under cursor or marked area
-zle -N inplaceMkDirs && bindkey '^xM' inplaceMkDirs ## KEYB!
+zle -N inplaceMkDirs
 
 #v1# set number of lines to display per page
 HELP_LINES_PER_PAGE=20
@@ -1199,10 +1175,10 @@ help_zle_parse_keybindings()
             if [[ "$cline" == (#s)[[:space:]]#\#k\#[[:space:]]##(#b)(*)[[:space:]]#(#e) ]]; then
                 lastkeybind_desc="$match[*]"
                 num_lines_elapsed=0
-            #zsh pattern: matches lines that set a keybinding using bindkey or compdef -k
+            #zsh pattern: matches lines that set a keybinding using bind2map, bindkey or compdef -k
             #             ignores lines that are commentend out
             #             grabs first in '' or "" enclosed string with length between 1 and 6 characters
-            elif [[ "$cline" == [^#]#(bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*)  ]]; then
+            elif [[ "$cline" == [^#]#(bind2maps[[:space:]](*)-s|bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*)  ]]; then
                 #description prevously found ? description not more than 2 lines away ? keybinding not empty ?
                 if [[ -n $lastkeybind_desc && $num_lines_elapsed -lt 2 && -n $match[1] ]]; then
                     #substitute keybinding string with something readable
@@ -1249,8 +1225,7 @@ help-zle()
     help_zle_sln=$((help_zle_sln + HELP_LINES_PER_PAGE))
     zle -M "${(F)help_zle_lines[sln,help_zle_sln-1]}"
 }
-#k# display help for keybindings and ZLE
-zle -N help-zle && bindkey '^xz' help-zle # note: cycle pages with consecutive use of '^xz' ## KEYB!
+zle -N help-zle
 
 ## complete word from currently visible Screen or Tmux buffer.
 if check_com -c screen || check_com -c tmux; then
@@ -1292,7 +1267,7 @@ function zrcautozle() {
 }
 
 function zrcgotwidget() {
-    (( ${+widgets[$i]} ))
+    (( ${+widgets[$1]} ))
 }
 
 function zrcgotkeymap() {
@@ -1315,7 +1290,7 @@ zstyle ':completion:hist-complete:*' completer _history
 typeset -ga grml_missing_features
 
 function zrcbindkey() {
-    if (( ARGC && ${+widgets[${argv[-1]}]} )); then
+    if (( ARGC )) && zrcgotwidget ${argv[-1]}; then
         bindkey "$@"
     fi
 }
@@ -1330,7 +1305,12 @@ function bind2maps () {
     done
     shift
 
-    sequence="${key[$1]}"
+    if [[ "$1" == "-s" ]]; then
+        shift
+        sequence="$1"
+    else
+        sequence="${key[$1]}"
+    fi
     widget="$2"
 
     [[ -z "$sequence" ]] && return 1
@@ -1342,9 +1322,11 @@ function bind2maps () {
 
 if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
     function zle-smkx () {
+        emulate -L zsh
         printf '%s' ${terminfo[smkx]}
     }
     function zle-rmkx () {
+        emulate -L zsh
         printf '%s' ${terminfo[rmkx]}
     }
     function zle-line-init () {
@@ -1377,6 +1359,19 @@ key=(
     BackTab  "${terminfo[kcbt]}"
 )
 
+# Guidelines for adding key bindings:
+#
+#   - Do not add hardcoded escape sequences, to enable non standard key
+#     combinations such as Ctrl-Meta-Left-Cursor. They are not easily portable.
+#
+#   - Adding Ctrl characters, such as '^b' is okay; note that '^b' and '^B' are
+#     the same key.
+#
+#   - All keys from the $key[] mapping are obviously okay.
+#
+#   - Most terminals send "ESC x" when Meta-x is pressed. Thus, sequences like
+#     '\ex' are allowed in here as well.
+
 bind2maps emacs             -- Home   beginning-of-somewhere
 bind2maps       viins vicmd -- Home   vi-beginning-of-line
 bind2maps emacs             -- End    end-of-somewhere
@@ -1392,92 +1387,107 @@ bind2maps       viins vicmd -- Left   vi-backward-char
 bind2maps emacs             -- Right  forward-char
 bind2maps       viins vicmd -- Right  vi-forward-char
 bind2maps       viins vicmd -- Right  vi-forward-char
-
-if zrcgotkeymap menuselect; then
-    bind2maps menuselect -- BackTab reverse-menu-complete
-
-    #k# menu selection: pick item but stay in the menu
-    zrcbindkey -M menuselect '\e^M' accept-and-menu-complete
-    # also use + and INSERT since it's easier to press repeatedly
-    zrcbindkey -M menuselect "+" accept-and-menu-complete
-    zrcbindkey -M menuselect "^[[2~" accept-and-menu-complete
-
-    # accept a completion and try to complete again by using menu
-    # completion; very useful with completing directories
-    # by using 'undo' one's got a simple file browser
-    zrcbindkey -M menuselect '^o' accept-and-infer-next-history
-fi
-
+#k# Perform abbreviation expansion
+bind2maps emacs viins       -- -s '^x.' zleiab
+#k# Display list of abbreviations that would expand
+bind2maps emacs viins       -- -s '^xb' help-show-abk
+#k# mkdir -p <dir> from string under cursor or marked area
+bind2maps emacs viins       -- -s '^xM' inplaceMkDirs
+#k# display help for keybindings and ZLE
+bind2maps emacs viins       -- -s '^xz' help-zle
 #k# Insert files and test globbing
-zrcbindkey "^xf" insert-files # C-x-f
-
+bind2maps emacs viins       -- -s "^xf" insert-files
 #k# Edit the current line in \kbd{\$EDITOR}
-zrcbindkey '\ee' edit-command-line
-
-## use Ctrl-left-arrow and Ctrl-right-arrow for jumping to word-beginnings on the CL
-zrcbindkey "\e[5C" forward-word
-zrcbindkey "\e[5D" backward-word
-zrcbindkey "\e[1;5C" forward-word
-zrcbindkey "\e[1;5D" backward-word
-## the same for alt-left-arrow and alt-right-arrow
-zrcbindkey '^[[1;3C' forward-word
-zrcbindkey '^[[1;3D' backward-word
-
+bind2maps emacs viins       -- -s '\ee' edit-command-line
 #k# search history backward for entry beginning with typed text
-zrcbindkey '^xp'   history-beginning-search-backward-end
+bind2maps emacs viins       -- -s '^xp' history-beginning-search-backward-end
 #k# search history forward for entry beginning with typed text
-zrcbindkey '^xP'   history-beginning-search-forward-end
+bind2maps emacs viins       -- -s '^xP' history-beginning-search-forward-end
 #k# search history backward for entry beginning with typed text
-zrcbindkey "\e[5~" history-beginning-search-backward-end # PageUp
+bind2maps emacs viins       -- PageUp history-beginning-search-backward-end
 #k# search history forward for entry beginning with typed text
-zrcbindkey "\e[6~" history-beginning-search-forward-end  # PageDown
+bind2maps emacs viins       -- PageDown history-beginning-search-forward-end
+bind2maps emacs viins       -- -s "^x^h" commit-to-history
+#k# Kill left-side word or everything up to next slash
+bind2maps emacs viins       -- -s '\ev' slash-backward-kill-word
+#k# Kill left-side word or everything up to next slash
+bind2maps emacs viins       -- -s '\e^h' slash-backward-kill-word
+#k# Kill left-side word or everything up to next slash
+bind2maps emacs viins       -- -s '\e^?' slash-backward-kill-word
+# Do history expansion on space:
+bind2maps emacs viins       -- -s ' ' magic-space
+#k# Trigger menu-complete
+bind2maps emacs viins       -- -s '\ei' menu-complete  # menu completion via esc-i
+#k# Insert a timestamp on the command line (yyyy-mm-dd)
+bind2maps emacs viins       -- -s '^ed' insert-datestamp
+#k# Insert last typed word
+bind2maps emacs viins       -- -s "\em" insert-last-typed-word
+#k# A smart shortcut for \kbd{fg<enter>}
+bind2maps emacs viins       -- -s '^z' grml-zsh-fg
+#k# prepend the current command with "sudo"
+bind2maps emacs viins       -- -s "^os" sudo-command-line
+#k# jump to after first word (for adding options)
+bind2maps emacs viins       -- -s '^x1' jump_after_first_word
+#k# complete word from history with menu
+bind2maps emacs viins       -- -s "^x^x" hist-complete
 
 # insert unicode character
 # usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an ยง
 # See for example http://unicode.org/charts/ for unicode characters code
 #k# Insert Unicode character
-zrcbindkey '^xi' insert-unicode-char
+bind2maps emacs viins       -- -s '^xi' insert-unicode-char
 
-#m# k Shift-tab Perform backwards menu completion
-if [[ -n "$terminfo[kcbt]" ]]; then
-    zrcbindkey "$terminfo[kcbt]" reverse-menu-complete
-elif [[ -n "$terminfo[cbt]" ]]; then # required for GNU screen
-    zrcbindkey "$terminfo[cbt]"  reverse-menu-complete
+# use the new *-pattern-* widgets for incremental history search
+if zrcgotwidget history-incremental-pattern-search-backward; then
+    for seq wid in '^r' history-incremental-pattern-search-backward \
+                   '^s' history-incremental-pattern-search-forward
+    do
+        bind2maps emacs viins vicmd -- -s $seq $wid
+    done
 fi
 
-#k# Toggle abbreviation expansion on/off
-zrcbindkey '^xA' grml_toggle_abbrev
-zrcbindkey "^x^h" commit-to-history
+if zrcgotkeymap menuselect; then
+    #m# k Shift-tab Perform backwards menu completion
+    bind2maps menuselect -- BackTab reverse-menu-complete
 
-#k# Kill left-side word or everything up to next slash
-zrcbindkey '\ev' slash-backward-kill-word
-#k# Kill left-side word or everything up to next slash
-zrcbindkey '\e^h' slash-backward-kill-word
-#k# Kill left-side word or everything up to next slash
-zrcbindkey '\e^?' slash-backward-kill-word
+    #k# menu selection: pick item but stay in the menu
+    bind2maps menuselect -- -s '\e^M' accept-and-menu-complete
+    # also use + and INSERT since it's easier to press repeatedly
+    bind2maps menuselect -- -s '+' accept-and-menu-complete
+    bind2maps menuselect -- Insert accept-and-menu-complete
 
-# use the new *-pattern-* widgets for incremental history search
-if zrcgotwidget history-incremental-pattern-search-backward; then
-    zrcbindkey '^r' history-incremental-pattern-search-backward
-    zrcbindkey '^s' history-incremental-pattern-search-forward
+    # accept a completion and try to complete again by using menu
+    # completion; very useful with completing directories
+    # by using 'undo' one's got a simple file browser
+    bind2maps menuselect -- -s '^o' accept-and-infer-next-history
 fi
 
-# Do history expansion on space:
-zrcbindkey ' ' magic-space
-#k# Trigger menu-complete
-zrcbindkey '\ei' menu-complete  # menu completion via esc-i
-#k# Insert a timestamp on the command line (yyyy-mm-dd)
-zrcbindkey '^ed' insert-datestamp
-#k# Insert last typed word
-zrcbindkey "\em" insert-last-typed-word
-#k# A smart shortcut for \kbd{fg<enter>}
-zrcbindkey '^z' grml-zsh-fg
-#k# prepend the current command with "sudo"
-zrcbindkey "^os" sudo-command-line
-#k# jump to after first word (for adding options)
-zrcbindkey '^x1' jump_after_first_word
-#k# complete word from history with menu
-zrcbindkey "^x^x" hist-complete
+# Finally, here are still a few hardcoded escape sequences; Special sequences
+# like Ctrl-<Cursor-key> etc do suck a fair bit, because they are not
+# standardised and most of the time are not available in a terminals terminfo
+# entry.
+#
+# While we do not encourage adding bindings like these, we will keep these for
+# backward compatibility.
+
+## use Ctrl-left-arrow and Ctrl-right-arrow for jumping to word-beginnings on
+## the command line.
+# URxvt sequences:
+bind2maps emacs viins vicmd -- -s '\eOc' forward-word
+bind2maps emacs viins vicmd -- -s '\eOd' backward-word
+# These are for xterm:
+bind2maps emacs viins vicmd -- -s '\e[1;5C' forward-word
+bind2maps emacs viins vicmd -- -s '\e[1;5D' backward-word
+## the same for alt-left-arrow and alt-right-arrow
+# URxvt again:
+bind2maps emacs viins vicmd -- -s '\e\e[C' forward-word
+bind2maps emacs viins vicmd -- -s '\e\e[D' backward-word
+# Xterm again:
+bind2maps emacs viins vicmd -- -s '^[[1;3C' forward-word
+bind2maps emacs viins vicmd -- -s '^[[1;3D' backward-word
+# Also try ESC Left/Right:
+bind2maps emacs viins vicmd -- -s '\e'${key[Right]} forward-word
+bind2maps emacs viins vicmd -- -s '\e'${key[Left]}  backward-word
 
 # autoloading
 
@@ -1531,6 +1541,7 @@ if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
 fi
 
 chpwd() {
+    if (( $DIRSTACKSIZE <= 0 )) || [[ -z $DIRSTACKFILE ]]; then return; fi
     local -ax my_stack
     my_stack=( ${PWD} ${dirstack} )
     if is42 ; then
@@ -1586,7 +1597,16 @@ fi # is433
 # set colors for use in prompts (modern zshs allow for the use of %F{red}foo%f
 # in prompts to get a red "foo" embedded, but it's good to keep these for
 # backwards compatibility).
-if zrcautoload colors && colors 2>/dev/null ; then
+if is437; then
+    BLUE="%F{blue}"
+    RED="%F{red}"
+    GREEN="%F{green}"
+    CYAN="%F{cyan}"
+    MAGENTA="%F{magenta}"
+    YELLOW="%F{yellow}"
+    WHITE="%F{white}"
+    NO_COLOR="%f"
+elif zrcautoload colors && colors 2>/dev/null ; then
     BLUE="%{${fg[blue]}%}"
     RED="%{${fg_bold[red]}%}"
     GREEN="%{${fg[green]}%}"
@@ -1669,21 +1689,61 @@ if zrcautoload vcs_info; then
     fi
 fi
 
+typeset -A grml_vcs_coloured_formats
+typeset -A grml_vcs_plain_formats
+
+grml_vcs_plain_formats=(
+    format "(%s%)-[%b] "    "zsh: %r"
+    actionformat "(%s%)-[%b|%a] " "zsh: %r"
+    rev-branchformat "%b:%r"
+)
+
+grml_vcs_coloured_formats=(
+    format "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOR} "
+    actionformat "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOR} "
+    rev-branchformat "%b${RED}:${YELLOW}%r"
+)
+
+typeset GRML_VCS_COLOUR_MODE=xxx
+
+grml_vcs_info_toggle_colour () {
+    emulate -L zsh
+    if [[ $GRML_VCS_COLOUR_MODE == plain ]]; then
+        grml_vcs_info_set_formats coloured
+    else
+        grml_vcs_info_set_formats plain
+    fi
+    return 0
+}
+
+grml_vcs_info_set_formats () {
+    emulate -L zsh
+    #setopt localoptions xtrace
+    local mode=$1 AF F BF
+    if [[ $mode == coloured ]]; then
+        AF=${grml_vcs_coloured_formats[actionformat]}
+        F=${grml_vcs_coloured_formats[format]}
+        BF=${grml_vcs_coloured_formats[rev-branchformat]}
+        GRML_VCS_COLOUR_MODE=coloured
+    else
+        AF=${grml_vcs_plain_formats[actionformat]}
+        F=${grml_vcs_plain_formats[format]}
+        BF=${grml_vcs_plain_formats[rev-branchformat]}
+        GRML_VCS_COLOUR_MODE=plain
+    fi
+
+    zstyle ':vcs_info:*'              actionformats "$AF" "zsh: %r"
+    zstyle ':vcs_info:*'              formats       "$F"  "zsh: %r"
+    zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat  "$BF"
+    return 0
+}
+
 # Change vcs_info formats for the grml prompt. The 2nd format sets up
 # $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title.
-# TODO: The included vcs_info() version still uses $VCS_INFO_message_N_.
-#       That needs to be the use of $VCS_INFO_message_N_ needs to be changed
-#       to $vcs_info_msg_N_ as soon as we use the included version.
 if [[ "$TERM" == dumb ]] ; then
-    zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] " "zsh: %r"
-    zstyle ':vcs_info:*' formats       "(%s%)-[%b] "    "zsh: %r"
+    grml_vcs_info_set_formats plain
 else
-    # these are the same, just with a lot of colors:
-    zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOR} " \
-                                       "zsh: %r"
-    zstyle ':vcs_info:*' formats       "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOR}%} " \
-                                       "zsh: %r"
-    zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r"
+    grml_vcs_info_set_formats coloured
 fi
 
 # Now for the fun part: The grml prompt themes in `promptsys' mode of operation
@@ -1825,7 +1885,7 @@ grml_prompt_pre_default=(
     newline           ''
     path              '%B'
     percent           ''
-    rc                '%F{red}'
+    rc                '%B%F{red}'
     rc-always         ''
     sad-smiley        ''
     shell-level       '%F{red}'
@@ -1846,7 +1906,7 @@ grml_prompt_post_default=(
     newline           ''
     path              '%b'
     percent           ''
-    rc                '%f'
+    rc                '%f%b'
     rc-always         ''
     sad-smiley        ''
     shell-level       '%f'
@@ -1876,6 +1936,14 @@ grml_prompt_token_default=(
     vcs               '0'
 )
 
+function grml_theme_has_token () {
+    if (( ARGC != 1 )); then
+        printf 'usage: grml_theme_has_token <name>\n'
+        return 1
+    fi
+    (( ${+grml_prompt_token_default[$1]} ))
+}
+
 function GRML_theme_add_token_usage () {
     cat <<__EOF__
   Usage: grml_theme_add_token <name> [-f|-i] <token/function> [<pre> <post>]
@@ -1897,6 +1965,11 @@ function GRML_theme_add_token_usage () {
     return value is expected in the \$REPLY parameter. The use of these
     options is mutually exclusive.
 
+    There is a utility function \`grml_theme_has_token', which you can use
+    to test if a token exists before trying to add it. This can be a guard
+    for situations in which a \`grml_theme_add_token' call may happen more
+    than once.
+
   Example:
 
     To add a new token \`day' that expands to the current weekday in the
@@ -1960,7 +2033,7 @@ grml_theme_add_token: <pre> and <post> need to by specified _both_!\n\n'
         shift 2
     fi
 
-    if (( ${+grml_prompt_token_default[$name]} )); then
+    if grml_theme_has_token $name; then
         printf '
 grml_theme_add_token: Token `%s'\'' exists! Giving up!\n\n' $name
         GRML_theme_add_token_usage
@@ -2005,7 +2078,7 @@ function grml_prompt_addto () {
     for it in "${items[@]}"; do
         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" pre apre \
             || apre=${grml_prompt_pre_default[$it]}
-        zstyle -s ":prompt:grml:${grmltheme}:${lr}:$it" post apost \
+        zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" post apost \
             || apost=${grml_prompt_post_default[$it]}
         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
             || new=${grml_prompt_token_default[$it]}
@@ -2129,7 +2202,7 @@ if is437; then
         unset i
         zstyle ':prompt:grml(|-large|-chroot):right:setup' use-rprompt false
     elif (( EUID == 0 )); then
-        zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%F{red}'
+        zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%B%F{red}'
     fi
 
     # Finally enable one of the prompts.
@@ -2253,8 +2326,8 @@ fi
 
 # do we have GNU ls with color-support?
 if [[ "$TERM" != dumb ]]; then
-    #a1# List files with colors (\kbd{ls -b -CF \ldots})
-    alias ls='ls -b -CF '${ls_options:+"${ls_options[*]}"}
+    #a1# List files with colors (\kbd{ls -CF \ldots})
+    alias ls='ls -CF '${ls_options:+"${ls_options[*]}"}
     #a1# List all files, with colors (\kbd{ls -la \ldots})
     alias la='ls -la '${ls_options:+"${ls_options[*]}"}
     #a1# List files with long colored list, without dotfiles (\kbd{ls -l \ldots})
@@ -2264,7 +2337,7 @@ if [[ "$TERM" != dumb ]]; then
     #a1# List files with long colored list, append qualifier to filenames (\kbd{ls -lF \ldots})\\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
     alias l='ls -lF '${ls_options:+"${ls_options[*]}"}
 else
-    alias ls='ls -b -CF'
+    alias ls='ls -CF'
     alias la='ls -la'
     alias ll='ls -l'
     alias lh='ls -hAl'
@@ -2492,6 +2565,7 @@ compdef _functions freload
 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
 sll() {
     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
+    local file
     for file in "$@" ; do
         while [[ -h "$file" ]] ; do
             ls -l $file
@@ -2504,26 +2578,31 @@ sll() {
 #   PAGER='less -Mr' - If so, the use of $PAGER here needs fixing
 # with respect to wordsplitting. (ie. ${=PAGER})
 if check_com -c $PAGER ; then
-    #f3# View Debian's changelog of a given package
+    #f3# View Debian's changelog of given package(s)
     dchange() {
         emulate -L zsh
-        if [[ -r /usr/share/doc/$1/changelog.Debian.gz ]] ; then
-            $PAGER /usr/share/doc/$1/changelog.Debian.gz
-        elif [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
-            $PAGER /usr/share/doc/$1/changelog.gz
-        else
-            if check_com -c aptitude ; then
-                echo "No changelog for package $1 found, using aptitude to retrieve it."
-                if isgrml ; then
-                    aptitude -t unstable changelog $1
+        [[ -z "$1" ]] && printf 'Usage: %s <package_name(s)>\n' "$0" && return 1
+
+        local package
+        for package in "$@" ; do
+            if [[ -r /usr/share/doc/${package}/changelog.Debian.gz ]] ; then
+                $PAGER /usr/share/doc/${package}/changelog.Debian.gz
+            elif [[ -r /usr/share/doc/${package}/changelog.gz ]] ; then
+                $PAGER /usr/share/doc/${package}/changelog.gz
+            elif [[ -r /usr/share/doc/${package}/changelog ]] ; then
+                $PAGER /usr/share/doc/${package}/changelog
+            else
+                if check_com -c aptitude ; then
+                    echo "No changelog for package $package found, using aptitude to retrieve it."
+                    aptitude changelog "$package"
+                elif check_com -c apt-get ; then
+                    echo "No changelog for package $package found, using apt-get to retrieve it."
+                    apt-get changelog "$package"
                 else
-                    aptitude changelog $1
+                    echo "No changelog for package $package found, sorry."
                 fi
-            else
-                echo "No changelog for package $1 found, sorry."
-                return 1
             fi
-        fi
+        done
     }
     _dchange() { _files -W /usr/share/doc -/ }
     compdef _dchange dchange
@@ -2709,11 +2788,6 @@ if check_com vim; then
     }
 fi
 
-# make a backup of a file
-bk() {
-    cp -a "$1" "${1}_$(date --iso-8601=seconds)"
-}
-
 ssl_hashes=( sha512 sha256 sha1 md5 )
 
 for sh in ${ssl_hashes}; do
@@ -2901,8 +2975,13 @@ modified() {
 check_com new || alias new=modified
 
 # use colors when GNU grep with color-support
-#a2# Execute \kbd{grep -{}-color=auto}
-(( $#grep_options > 0 )) && alias grep='grep '${grep_options:+"${grep_options[*]}"}
+if (( $#grep_options > 0 )); then
+    o=${grep_options:+"${grep_options[*]}"}
+    #a2# Execute \kbd{grep -{}-color=auto}
+    alias grep='grep '$o
+    alias egrep='egrep '$o
+    unset o
+fi
 
 # Translate DE<=>EN
 # 'translate' looks up fot a word in a file with language-to-language