]> git.alrj.org Git - zsh.d.git/commitdiff
Update git part of prompt.
authorAmand Tihon <amand.tihon@iba-group.com>
Wed, 17 Feb 2010 15:07:27 +0000 (16:07 +0100)
committerAmand Tihon <amand.tihon@iba-group.com>
Wed, 17 Feb 2010 15:07:27 +0000 (16:07 +0100)
* Only recalculate git variables if needed.
* Add symbols about repository status (clean, new, staged).
* Some refactoring.

S60_git
S90_prompt

diff --git a/S60_git b/S60_git
index 8926a73476a209f1a479ad1b13b882333e05cb13..037e8b3aebb190ce5819caa6ba70b754f573e734 100644 (file)
--- a/S60_git
+++ b/S60_git
@@ -1,14 +1,97 @@
 #! /usr/bin/zsh
 
 export __ZSH_GIT_BASEDIR=""
-export __ZSH_GIT_BRANCH=""
 export __ZSH_GIT_SUBDIR=""
-export __ZSH_GIT_STATE=""
+export __ZSH_GIT_BRANCH=""
+export __ZSH_GIT_ACTION=""
+export __ZSH_GIT_STATUS=""
 export __ZSH_GIT_VARS_INVALID=1
+export __ZSH_GIT_STATUS_INVALID=1
+
+
+git_chpwd() {
+  # On cd, invalidate git status in prompt
+  export __ZSH_GIT_VARS_INVALID=1
+}
+
+
+git_preexec() {
+  # On git command, invalidate git status in prompt
+  case "$1" in
+    git*)
+      export __ZSH_GIT_VARS_INVALID=1
+      ;;
+  esac
+
+  # *any* command could invalidate the repository status (new file, ...)
+  export __ZSH_GIT_STATUS_INVALID=1
+}
+
+
+git_get_status() {
+    # Return only git status
+    local gitstat gitstatus
+
+    gitstat=$(git status 2> /dev/null | grep '\(# Untracked\|# Changes\|# Changed but not updated:\)')
+    gitstatus=""
+
+    if [[ $(echo ${gitstat} | grep -c "^# Changes to be committed:$") > 0 ]]; then
+      gitstatus='+'
+    fi
+
+    if [[ $(echo ${gitstat} | grep -c "^\# Changed but not updated:$") > 0 ]]; then
+      gitstatus="${gitstatus}!"
+    fi
+
+    if [[ $(echo ${gitstat} | grep -c "^# Untracked files:$") > 0 ]]; then
+      gitstatus="${gitstatus}?"
+    fi
+
+    echo $gitstatus
+}
+
 
 git_parse() {
+    # psvar[3] == current action (merge, rebase, ...)
+    # psvar[4] == current branch
+    # psvar[5] == repository base directory
+    # psvar[6] == current subdir into repository
+    # psvar[7] == status (untracked, unstaged, staged)
+
+    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
+
+      # reuse previous values
+      psvar[3]=${__ZSH_GIT_ACTION}
+      psvar[4]=${__ZSH_GIT_BRANCH}
+      psvar[5]=${__ZSH_GIT_BASEDIR}
+      psvar[6]=${__ZSH_GIT_SUBDIR}
+      psvar[7]=${__ZSH_GIT_STATUS}
+
+      return
+    fi
 
-    local git_dir ref base_dir sub_dir action branch
+    # If only status has been invalidated
+    if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "1" ]]; then
+
+      # reuse previous values
+      psvar[3]=${__ZSH_GIT_ACTION}
+      psvar[4]=${__ZSH_GIT_BRANCH}
+      psvar[5]=${__ZSH_GIT_BASEDIR}
+      psvar[6]=${__ZSH_GIT_SUBDIR}
+
+      export __ZSH_GIT_STATUS=$(git_get_status)
+      psvar[7]=${__ZSH_GIT_STATUS}
+
+      export __ZSH_GIT_STATUS_INVALID=0
+      return
+    fi
+
+
+    # Git prompt variables are invalid. Update them.
 
     git_dir=$(git rev-parse --git-dir 2> /dev/null) || return
 
@@ -18,25 +101,25 @@ git_parse() {
     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"
@@ -45,10 +128,28 @@ git_parse() {
         branch="$(cut -c1-7 "$git_dir/HEAD")..."
     fi
 
+    # Status
+    gitstatus=`git_get_status`
+
     # Got here, we're in git
+    psvar[3]=${action}
     psvar[4]=${branch#refs/heads/}
     psvar[5]=${base_dir}
     psvar[6]=${sub_dir}
+    psvar[7]=${gitstatus}
+    
+    # Save for next time
+    export __ZSH_GIT_BASEDIR="${base_dir}"
+    export __ZSH_GIT_SUBDIR="${sub_dir}"
+    export __ZSH_GIT_BRANCH="${branch#refs/heads/}"
+    export __ZSH_GIT_ACTION="${action}"
+    export __ZSH_GIT_STATUS="${gitstatus}"
+
+    export __ZSH_GIT_VARS_INVALID=0
+    export __ZSH_GIT_STATUS_INVALID=0
 }
 
+
+chpwd_functions+='git_chpwd'
+preexec_functions+='git_preexec'
 precmd_functions+='git_parse'
index a9d379a11fc857ef92bbafeae72d9f56fab2098e..9ca2cd6222d79d8b8eb91b1e1c4ab75d92556ac5 100644 (file)
@@ -27,7 +27,7 @@ _exitcode="%(?::${C_BRED}[ %1v ]${C_NO}
 )$(true)"
 
 _action="%(3v,%3v%,)"
-_path='${C_GREEN}%(5v,%20<..<%5v%<<${C_NO}${C_MAGENTA}@%4v%3v${C_NO}${C_GREEN}/%15<..<%6v%<<,%25<..<%~%<<)${C_NO}'
+_path='${C_GREEN}%(5v,%20<..<%5v%<<${C_NO}${C_MAGENTA}@%4v%3v${C_BYELLOW}%7v${C_NO}${C_GREEN}/%15<..<%6v%<<,%25<..<%~%<<)${C_NO}'
 
 
 #