]> git.alrj.org Git - zsh.d.git/blob - S60_git
Update git part of prompt.
[zsh.d.git] / S60_git
1 #! /usr/bin/zsh
2
3 export __ZSH_GIT_BASEDIR=""
4 export __ZSH_GIT_SUBDIR=""
5 export __ZSH_GIT_BRANCH=""
6 export __ZSH_GIT_ACTION=""
7 export __ZSH_GIT_STATUS=""
8 export __ZSH_GIT_VARS_INVALID=1
9 export __ZSH_GIT_STATUS_INVALID=1
10
11
12 git_chpwd() {
13   # On cd, invalidate git status in prompt
14   export __ZSH_GIT_VARS_INVALID=1
15 }
16
17
18 git_preexec() {
19   # On git command, invalidate git status in prompt
20   case "$1" in
21     git*)
22       export __ZSH_GIT_VARS_INVALID=1
23       ;;
24   esac
25
26   # *any* command could invalidate the repository status (new file, ...)
27   export __ZSH_GIT_STATUS_INVALID=1
28 }
29
30
31 git_get_status() {
32     # Return only git status
33     local gitstat gitstatus
34
35     gitstat=$(git status 2> /dev/null | grep '\(# Untracked\|# Changes\|# Changed but not updated:\)')
36     gitstatus=""
37
38     if [[ $(echo ${gitstat} | grep -c "^# Changes to be committed:$") > 0 ]]; then
39       gitstatus='+'
40     fi
41
42     if [[ $(echo ${gitstat} | grep -c "^\# Changed but not updated:$") > 0 ]]; then
43       gitstatus="${gitstatus}!"
44     fi
45
46     if [[ $(echo ${gitstat} | grep -c "^# Untracked files:$") > 0 ]]; then
47       gitstatus="${gitstatus}?"
48     fi
49
50     echo $gitstatus
51 }
52
53
54 git_parse() {
55     # psvar[3] == current action (merge, rebase, ...)
56     # psvar[4] == current branch
57     # psvar[5] == repository base directory
58     # psvar[6] == current subdir into repository
59     # psvar[7] == status (untracked, unstaged, staged)
60
61     local git_dir ref base_dir sub_dir action branch gitstat gitstatus
62
63
64     # If nothing has been invalidated
65     if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "0" ]]; then
66
67       # reuse previous values
68       psvar[3]=${__ZSH_GIT_ACTION}
69       psvar[4]=${__ZSH_GIT_BRANCH}
70       psvar[5]=${__ZSH_GIT_BASEDIR}
71       psvar[6]=${__ZSH_GIT_SUBDIR}
72       psvar[7]=${__ZSH_GIT_STATUS}
73
74       return
75     fi
76
77     # If only status has been invalidated
78     if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "1" ]]; then
79
80       # reuse previous values
81       psvar[3]=${__ZSH_GIT_ACTION}
82       psvar[4]=${__ZSH_GIT_BRANCH}
83       psvar[5]=${__ZSH_GIT_BASEDIR}
84       psvar[6]=${__ZSH_GIT_SUBDIR}
85
86       export __ZSH_GIT_STATUS=$(git_get_status)
87       psvar[7]=${__ZSH_GIT_STATUS}
88
89       export __ZSH_GIT_STATUS_INVALID=0
90       return
91     fi
92
93
94     # Git prompt variables are invalid. Update them.
95
96     git_dir=$(git rev-parse --git-dir 2> /dev/null) || return
97
98     base_dir=${$(readlink -f "$git_dir/..")/$HOME/'~'}
99
100     sub_dir=$(git rev-parse --show-prefix)
101     sub_dir=${sub_dir%/}
102     ref=$(git symbolic-ref HEAD 2> /dev/null) || return
103
104     action=""
105
106     if [ -d "$git_dir/../.dotest" ]; then
107       if [ -f "$git_dir/../.dotest/rebasing" ]; then
108         action="-rebase"
109       elif [ -f "$git_dir/../.dotest/applying" ]; then
110         action="-am"
111       else
112         action="-am-rebase"
113       fi
114       branch="$ref"
115     elif [ -f "$git_dir/.dotest-merge/interactive" ]; then
116       action="-rebase-i"
117       branch="$(cat "$git_dir/.dotest-merge/head-name")"
118     elif [ -d "$git_dir/.dotest-merge" ]; then
119       action="-rebase-m"
120       branch="$(cat "$git_dir/.dotest-merge/head-name")"
121     elif [ -f "$git_dir/MERGE_HEAD" ]; then
122       action="-merge"
123       branch="$ref"
124     else
125       test -f "$git_dir/BISECT_LOG" && psvar[3]="bisect"
126       branch="$(git symbolic-ref HEAD 2>/dev/null)" || \
127         branch="$(git describe --exact-match HEAD 2>/dev/null)" || \
128         branch="$(cut -c1-7 "$git_dir/HEAD")..."
129     fi
130
131     # Status
132     gitstatus=`git_get_status`
133
134     # Got here, we're in git
135     psvar[3]=${action}
136     psvar[4]=${branch#refs/heads/}
137     psvar[5]=${base_dir}
138     psvar[6]=${sub_dir}
139     psvar[7]=${gitstatus}
140     
141     # Save for next time
142     export __ZSH_GIT_BASEDIR="${base_dir}"
143     export __ZSH_GIT_SUBDIR="${sub_dir}"
144     export __ZSH_GIT_BRANCH="${branch#refs/heads/}"
145     export __ZSH_GIT_ACTION="${action}"
146     export __ZSH_GIT_STATUS="${gitstatus}"
147
148     export __ZSH_GIT_VARS_INVALID=0
149     export __ZSH_GIT_STATUS_INVALID=0
150 }
151
152
153 chpwd_functions+='git_chpwd'
154 preexec_functions+='git_preexec'
155 precmd_functions+='git_parse'