]> git.alrj.org Git - zsh.d.git/blobdiff - S60_git
Add a wrapper for mc to stay in current directory upon exit
[zsh.d.git] / S60_git
diff --git a/S60_git b/S60_git
index 433cea7c193a4bca01fd3964fe162849c685fb64..1061cf575a0a04d47412070ac157bdf7cc2b71fa 100644 (file)
--- a/S60_git
+++ b/S60_git
 #! /usr/bin/zsh
 
+# Those can be used, for instance to construct the prompt:
+__ZSH_GIT_BASEDIR=""
+__ZSH_GIT_SUBDIR=""
+__ZSH_GIT_BRANCH=""
+__ZSH_GIT_ACTION=""
+__ZSH_GIT_STATUS=""
+
+__ZSH_GIT_VARS_INVALID=1
+__ZSH_GIT_STATUS_INVALID=1
+
+
+git_chpwd() {
+  # On cd, invalidate git status in prompt
+  __ZSH_GIT_VARS_INVALID=1
+  __ZSH_GIT_BASEDIR=""
+}
+
+
+git_preexec() {
+  # On git command, invalidate git status in prompt
+  case "$1" in
+    git*)
+      __ZSH_GIT_VARS_INVALID=1
+      ;;
+  esac
+
+  # *any* command could invalidate the repository status (new file, ...)
+  __ZSH_GIT_STATUS_INVALID=1
+}
+
+git_get_status() {
+    # Return only git status
+    local gitstat gitstatus
+
+    gitstat=$(LANG=C git status 2> /dev/null | grep '\(Untracked\|Changes\|Changed but not updated:\)')
+    # 'fix for mcedit parser
+    gitstatus=""
+
+    if [[ $(echo ${gitstat} | grep -c "^Changes to be committed:$") > 0 ]]; then
+      gitstatus='✚'
+    fi
+
+    if [[ $(echo ${gitstat} | grep -c "^Changed but not updated:$") > 0 || \
+          $(echo ${gitstat} | grep -c "^Changes not staged for commit:$") > 0 ]]; then
+      gitstatus="${gitstatus}✹"
+    fi
+
+    if [[ $(echo ${gitstat} | grep -c "^Untracked files:$") > 0 ]]; then
+      gitstatus="${gitstatus}★"
+    fi
+
+    if [[ -z $gitstatus ]]; then
+      gitstatus="%{${fg_bold[green]}%}✔%{$reset_color%}"
+    else
+      gitstatus="%{${fg_bold[yellow]}%}$gitstatus%{$reset_color%}"
+    fi
+
+    echo $gitstatus
+}
+
+
 git_parse() {
+    local git_dir ref base_dir sub_dir action branch gitstat gitstatus
+
+    # If nothing has been invalidated
+    if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "0" ]]; then
+      return
+    fi
+
+    # If only status has been invalidated
+    if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "1" ]]; then
+      __ZSH_GIT_STATUS=$(git_get_status)
+      __ZSH_GIT_STATUS_INVALID=0
+      return
+    fi
 
-    psvar=()
 
-    local git_dir ref base_dir sub_dir action branch
+    # Git prompt variables are invalid. Update them.
+
     git_dir=$(git rev-parse --git-dir 2> /dev/null) || return
 
-    base_dir=${$(readlink -f "$git_dir/..")/$HOME/'~'}
+    if [[ "$(git rev-parse --is-bare-repository)" == "true" ]]; then
+      base_dir=${$(readlink -f "$git_dir")/$HOME/'~'}
+      sub_dir=${$(pwd)#$(readlink -f "$git_dir")}
+    else
+      base_dir=${$(readlink -f "$git_dir/..")/$HOME/'~'}
+      sub_dir=${$(pwd)#$(readlink -f "$git_dir/..")}
+    fi
 
-    sub_dir=$(git rev-parse --show-prefix)
-    sub_dir=${sub_dir%/}
+    sub_dir=${sub_dir#/}
     ref=$(git symbolic-ref HEAD 2> /dev/null) || return
 
-    psvar[3]=""
+    action=""
 
     if [ -d "$git_dir/../.dotest" ]; then
       if [ -f "$git_dir/../.dotest/rebasing" ]; then
-        psvar[3]="-rebase"
+        action="-rebase"
       elif [ -f "$git_dir/../.dotest/applying" ]; then
-        psvar[3]="-am"
+        action="-am"
       else
-        psvar[3]="-am-rebase"
+        action="-am-rebase"
       fi
       branch="$ref"
     elif [ -f "$git_dir/.dotest-merge/interactive" ]; then
-      psvar[3]="-rebase-i"
+      action="-rebase-i"
       branch="$(cat "$git_dir/.dotest-merge/head-name")"
     elif [ -d "$git_dir/.dotest-merge" ]; then
-      psvar[3]="-rebase-m"
+      action="-rebase-m"
       branch="$(cat "$git_dir/.dotest-merge/head-name")"
     elif [ -f "$git_dir/MERGE_HEAD" ]; then
-      psvar[3]="-merge"
+      action="-merge"
       branch="$ref"
     else
-      test -f "$git_dir/BISECT_LOG" && psvar[3]="bisect"
+      test -f "$git_dir/BISECT_LOG" && action="-bisect"
       branch="$(git symbolic-ref HEAD 2>/dev/null)" || \
         branch="$(git describe --exact-match HEAD 2>/dev/null)" || \
         branch="$(cut -c1-7 "$git_dir/HEAD")..."
     fi
 
-    # Got here, we're in git
-    psvar[4]=${branch#refs/heads/}
-    psvar[5]=${base_dir}
-    psvar[6]=${sub_dir}
+
+    __ZSH_GIT_BASEDIR="${base_dir}"
+    __ZSH_GIT_SUBDIR="${sub_dir}"
+    __ZSH_GIT_BRANCH="${branch#refs/heads/}"
+    __ZSH_GIT_ACTION="${action}"
+    __ZSH_GIT_STATUS=`git_get_status`
+
+    __ZSH_GIT_VARS_INVALID=0
+    __ZSH_GIT_STATUS_INVALID=0
 }
 
+
+chpwd_functions+='git_chpwd'
+preexec_functions+='git_preexec'
 precmd_functions+='git_parse'