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