zshrc: Improve robustness of the bzr backend in vcs_info()
[grml-etc-core.git] / etc / zsh / zshrc
index 1c38fcd..c3535f2 100644 (file)
@@ -1026,8 +1026,8 @@ else
     GREEN=$'%{\e[1;32m%}'
     CYAN=$'%{\e[1;36m%}'
     WHITE=$'%{\e[1;37m%}'
-    MAGENTA='%{\e[1;35m%}'
-    YELLOW='%{\e[1;33m%}'
+    MAGENTA=$'%{\e[1;35m%}'
+    YELLOW=$'%{\e[1;33m%}'
     NO_COLOUR=$'%{\e[0m%}'
 fi
 
@@ -1037,10 +1037,11 @@ fi
 
 # vcs_info() documentation: {{{
 #
-# The vcs_info () feature can be configured via zstyle:
+# The vcs_info() feature can be configured via zstyle:
 #   First, the context in which we are working:
 #       :vcs_info:<vcs-string>
-#   ...where <vcs-string> is one of: git, hg, bzr, svn or svk
+#   ...where <vcs-string> is one of:
+#       - git, git-svn, hg, darcs, bzr, mtn, svn or svk
 #
 #   You can of course use ':vcs_info:*' to match all VCSs at once.
 #
@@ -1053,6 +1054,9 @@ fi
 #                         (like an interactive rebase or a merge conflict)
 #   enable              - check in the 'init' context. If set to false,
 #                         vcs_info() will do nothing.
+#   disable             - provide a list of systems, you don't want
+#                         the prompt to check for repositories (checked
+#                         in the 'init' context, too).
 #
 # The default values for these in all contexts are:
 #   promptformat        " (%s)-[%b|%a]-"
@@ -1070,17 +1074,48 @@ fi
 #
 # Not all vcs backends may support all replacements
 #
+# Examples:
+#   Don't use vcs_info at all (even though it's in your prompt):
+#   % zstyle ':vcs_info:*' enable false
+#
+#   Don't provide prompt info for bzr and svk:
+#   % zstyle ':vcs_info:*' disable bzr svk
+#
+#   Provide a prompt specifically for git:
+#   % zstyle ':vcs_info:git' promptformat       ' GIT, BABY! [%b]'
+#   % zstyle ':vcs_info:git' promptactionformat ' GIT ACTION! [%b|%a]'
+#
 # If you want colors, make sure you enclose the color codes in %{...%}, because
-# the string provided by vcs_info() is commonly used for prompts.
+# the string provided by vcs_info() is used for prompts.
 #
 #   Example: PROMPT='%(?..[%?]-)%3~%$(vcs_info)#'
 #
 # This *requires* 'setopt prompt_subst'.
 # }}}
-VCS_INFO_default_action_format=' (%s)-[%b|%a]-'
-VCS_INFO_default_format=' (%s)-[%b]-'
+VCS_INFO_adjust () { #{{{
+    [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
+    return 0
+}
+# }}}
+VCS_INFO_format () { # {{{
+    local msg
+
+    if [[ -n ${1} ]] ; then
+        zstyle -s ":vcs_info:${vcs}" promptactionformat msg
+        [[ -z ${msg} ]] && msg=' (%s)-[%b|%a]-'
+    else
+        zstyle -s ":vcs_info:${vcs}" promptformat msg
+        [[ -z ${msg} ]] && msg=' (%s)-[%b]-'
+    fi
+    printf '%s' ${msg}
+}
+# }}}
 VCS_INFO_realpath () { #{{{
     # replacing 'readlink -f', which is really not portable.
+
+    # If there *is* a chpwd() function unfunction it here.
+    # The *real* zsh does not loose its chpwd(), because we run
+    # in a different context (process substitution in $PROMPT).
     (( ${+functions[chpwd]} )) && unfunction chpwd
     setopt chaselinks
     cd $1 2>/dev/null && pwd
@@ -1101,7 +1136,7 @@ VCS_INFO_git_getaction () { #{{{
             else
                 gitaction="am/rebase"
             fi
-            print '%s' ${gitaction}
+            printf '%s' ${gitaction}
             return 0
         fi
     done
@@ -1142,6 +1177,7 @@ VCS_INFO_git_getbranch () { #{{{
        || [[ -d "${gitdir}/../.dotest" ]]   \
        || [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
+        [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/rebase-apply/head-name)"
 
     elif   [[ -f "${gitdir}/rebase-merge/interactive" ]] \
         || [[ -d "${gitdir}/rebase-merge" ]] ; then
@@ -1170,16 +1206,14 @@ VCS_INFO_git_get_data () { # {{{
     setopt localoptions extendedglob
     local gitdir gitbase gitbranch gitaction msg
 
-    gitdir="$(git rev-parse --git-dir 2> /dev/null)"
-
-    if [[ $? -eq 0 ]] ; then
-        gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"
-    fi
+    gitdir=${vcs_comm[gitdir]}
+    gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"
 
     if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
         return
     fi
 
+    VCS_INFO_adjust
     gitaction="$(VCS_INFO_git_getaction ${gitdir})"
     msg=$(VCS_INFO_format ${gitaction})
 
@@ -1189,20 +1223,39 @@ VCS_INFO_git_get_data () { # {{{
     printf '%s' ${msg}
 }
 # }}}
+VCS_INFO_darcs_get_data () { # {{{
+    local msg darcsbase
+
+    darcsbase=${vcs_comm[basedir]}
+    msg=$(VCS_INFO_format)
+    zformat -f msg "${msg}" "a:" "b:${darcsbase:t}" "s:${vcs}" "r:${darcsbase:t}" "R:${darcsbase}"
+    printf '%s' ${msg}
+}
+# }}}
 VCS_INFO_hg_get_data () { # {{{
     local msg hgbranch hgbase
 
-    hgbase=${1}
+    hgbase=${vcs_comm[basedir]}
     hgbranch=$(< ${hgbase}/.hg/branch)
     msg=$(VCS_INFO_format)
     zformat -f msg "${msg}" "a:" "b:${hgbranch}" "s:${vcs}" "r:${hgbase:t}" "R:${hgbase}"
     printf '%s' ${msg}
 }
 # }}}
+VCS_INFO_mtn_get_data () { # {{{
+    local msg mtnbranch mtnbase
+
+    mtnbase=${vcs_comm[basedir]}
+    mtnbranch=$(mtn status | awk '/Current branch:/{ sub("Current branch: ", ""); print }')
+    msg=$(VCS_INFO_format)
+    zformat -f msg "${msg}" "a:" "b:${mtnbranch}" "s:${vcs}" "r:${mtnbase:t}" "R:${mtnbase}"
+    printf '%s' ${msg}
+}
+# }}}
 VCS_INFO_svk_get_data () { # {{{
     local msg svkbranch svkbase
 
-    svkbase=${1}
+    svkbase=${vcs_comm[basedir]}
     svkbranch=${svkbase##*
   }
     svkbase=${svkbase%%
@@ -1231,12 +1284,10 @@ VCS_INFO_svn_get_data () { # {{{
 VCS_INFO_bzr_get_data () { # {{{
     local msg bzrbranch bzrbase bzrrevno i j
 
-    bzrbase=$(bzr info | sed -rne 's, *branch root: ,,p')
-    case ${bzrbase} in
-        .) bzrbase=${PWD} ;;
-    esac
+    bzrbase=$(bzr info 2>/dev/null | sed -rne 's, *branch root: ,,p')
+    bzrbase=$(VCS_INFO_realpath ${bzrbase})
 
-    bzr version-info | while read i j; do
+    bzr version-info 2> /dev/null | while read i j; do
         case "${i}" in
             revno:)
                 bzrrevno=${j} ;;
@@ -1253,43 +1304,74 @@ VCS_INFO_bzr_get_data () { # {{{
 # VCS_INFO_*_detect () {{{
 
 VCS_INFO_detect_by_dir() {
-    local tool=${1} dirname=${2}
-    local basedir="."
+    local dirname=${1}
+    local basedir="." realbasedir
+
+    realbasedir=$(VCS_INFO_realpath ${basedir})
+    while [[ ${realbasedir} != '/' ]]; do
+        if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
+            [[ -d ${basedir}/${dirname} ]] && \
+            [[ -f ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
+                break
+        else
+            [[ -d ${basedir}/${dirname} ]] && break
+        fi
 
-    check_com -c ${tool} || return 1
-    while [[ ! -d ${basedir}/${dirname} ]]; do
         basedir=${basedir}/..
-        [[ $(VCS_INFO_realpath ${basedir}) = "/" ]] && return 1
+        realbasedir=$(VCS_INFO_realpath ${basedir})
     done
 
-    printf '%s' $(VCS_INFO_realpath ${basedir})
+    [[ ${realbasedir} == "/" ]] && return 1
+    vcs_comm[basedir]=${realbasedir}
     return 0
 }
 
 VCS_INFO_bzr_detect() {
-    VCS_INFO_detect_by_dir 'bzr' '.bzr'
+    check_com -c bzr || return 1
+    vcs_comm[detect_need_file]=branch/format
+    VCS_INFO_detect_by_dir '.bzr'
+    return $?
+}
+
+VCS_INFO_darcs_detect() {
+    check_com -c darcs || return 1
+    vcs_comm[detect_need_file]=format
+    VCS_INFO_detect_by_dir '_darcs'
     return $?
 }
 
 VCS_INFO_git_detect() {
-    check_com -c git && git rev-parse --is-inside-work-tree &> /dev/null && return 0
+    if check_com -c git && git rev-parse --is-inside-work-tree &> /dev/null ; then
+        vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
+        [[ -d ${vcs_comm[gitdir]}/svn ]] && vcs_comm[overwrite_name]='git-svn'
+        return 0
+    fi
     return 1
 }
 
 VCS_INFO_hg_detect() {
-    VCS_INFO_detect_by_dir 'hg' '.hg'
+    check_com -c hg || return 1
+    vcs_comm[detect_need_file]=branch
+    VCS_INFO_detect_by_dir '.hg'
+    return $?
+}
+
+VCS_INFO_mtn_detect() {
+    check_com -c mtn || return 1
+    vcs_comm[detect_need_file]=revision
+    VCS_INFO_detect_by_dir '_MTN'
     return $?
 }
 
 VCS_INFO_svk_detect() {
-    local output
+    local basedir
 
     check_com -c svk || return 1
     [[ -f ~/.svk/config ]] || return 1
 
-    output=$(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
+    basedir=$(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
 
-    printf '%s' ${output}
+    vcs_comm[basedir]=${basedir}
     return 0
 }
 
@@ -1300,38 +1382,29 @@ VCS_INFO_svn_detect() {
 }
 
 # }}}
-VCS_INFO_format () { # {{{
-    local msg
-
-    if [[ -n ${1} ]] ; then
-        zstyle -s ":vcs_info:${vcs}" promptactionformat msg
-        [[ -z ${msg} ]] && msg=${VCS_INFO_default_action_format}
-    else
-        zstyle -s ":vcs_info:${vcs}" promptformat msg
-        [[ -z ${msg} ]] && msg=${VCS_INFO_default_format}
-    fi
-    printf '%s' ${msg}
-}
-# }}}
 vcs_info () { # {{{
-    local string output
+    local string
     local -i found
-    local -a VCSs
+    local -a VCSs disabled
     local -x vcs
+    local -Ax vcs_comm
 
     vcs="init"
     zstyle -T ":vcs_info:${vcs}" "enable" || return 0
+    zstyle -a ":vcs_info:${vcs}" "disable" disabled
 
-    VCSs=(git hg bzr svn svk)
+    VCSs=(git hg bzr darcs mtn svn svk)
 
     (( found = 0 ))
     for vcs in ${VCSs} ; do
-        output=$(VCS_INFO_${vcs}_detect) && (( found = 1 )) && break
+        [[ -n ${(M)disabled:#${vcs}} ]] && continue
+        vcs_comm=()
+        VCS_INFO_${vcs}_detect && (( found = 1 )) && break
     done
 
     (( found == 0 )) && return 0
 
-    string=$(VCS_INFO_${vcs}_get_data ${output}) || return 1
+    string=$(VCS_INFO_${vcs}_get_data) || return 1
     printf '%s' ${string}
     return 0
 }
@@ -2325,7 +2398,7 @@ bk() {
 # }}}
 
 # {{{ make sure our environment is clean regarding colors
-for color in BLUE RED GREEN CYAN WHITE ; unset $color
+for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
 # }}}
 
 # source another config file if present {{{