]>
Commit | Line | Data |
---|---|---|
690d8824 JH |
1 | # |
2 | # bash completion support for core Git. | |
3 | # | |
4 | # Copyright (C) 2006 Shawn Pearce | |
5 | # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). | |
6 | # | |
7 | # The contained completion routines provide support for completing: | |
8 | # | |
9 | # *) local and remote branch names | |
10 | # *) local and remote tag names | |
11 | # *) .git/remotes file names | |
12 | # *) git 'subcommands' | |
13 | # *) tree paths within 'ref:path/to/file' expressions | |
14 | # | |
15 | # To use these routines: | |
16 | # | |
17 | # 1) Copy this file to somewhere (e.g. ~/.git-completion.sh). | |
18 | # 2) Added the following line to your .bashrc: | |
19 | # source ~/.git-completion.sh | |
20 | # | |
21 | ||
873537fa SP |
22 | __gitdir () |
23 | { | |
24 | echo "${__git_dir:-$(git rev-parse --git-dir 2>/dev/null)}" | |
25 | } | |
26 | ||
690d8824 JH |
27 | __git_refs () |
28 | { | |
873537fa SP |
29 | local cmd i is_hash=y dir="${1:-$(__gitdir)}" |
30 | if [ -d "$dir" ]; then | |
690d8824 JH |
31 | cmd=git-peek-remote |
32 | else | |
33 | cmd=git-ls-remote | |
34 | fi | |
873537fa | 35 | for i in $($cmd "$dir" 2>/dev/null); do |
690d8824 JH |
36 | case "$is_hash,$i" in |
37 | y,*) is_hash=n ;; | |
38 | n,*^{}) is_hash=y ;; | |
39 | n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;; | |
40 | n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;; | |
41 | n,*) is_hash=y; echo "$i" ;; | |
42 | esac | |
43 | done | |
44 | } | |
45 | ||
46 | __git_refs2 () | |
47 | { | |
873537fa SP |
48 | local cmd i is_hash=y dir="${1:-$(__gitdir)}" |
49 | if [ -d "$dir" ]; then | |
690d8824 JH |
50 | cmd=git-peek-remote |
51 | else | |
52 | cmd=git-ls-remote | |
53 | fi | |
873537fa | 54 | for i in $($cmd "$dir" 2>/dev/null); do |
690d8824 JH |
55 | case "$is_hash,$i" in |
56 | y,*) is_hash=n ;; | |
57 | n,*^{}) is_hash=y ;; | |
58 | n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}:${i#refs/tags/}" ;; | |
59 | n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}:${i#refs/heads/}" ;; | |
60 | n,*) is_hash=y; echo "$i:$i" ;; | |
61 | esac | |
62 | done | |
63 | } | |
64 | ||
65 | __git_remotes () | |
66 | { | |
873537fa | 67 | local i ngoff IFS=$'\n' d="$(__gitdir)" |
56fc25f2 | 68 | shopt -q nullglob || ngoff=1 |
690d8824 | 69 | shopt -s nullglob |
873537fa SP |
70 | for i in "$d/remotes"/*; do |
71 | echo ${i#$d/remotes/} | |
690d8824 | 72 | done |
56fc25f2 | 73 | [ "$ngoff" ] && shopt -u nullglob |
873537fa | 74 | for i in $(git --git-dir="$d" repo-config --list); do |
56fc25f2 SP |
75 | case "$i" in |
76 | remote.*.url=*) | |
77 | i="${i#remote.}" | |
78 | echo "${i/.url=*/}" | |
79 | ;; | |
80 | esac | |
81 | done | |
690d8824 JH |
82 | } |
83 | ||
84 | __git_complete_file () | |
85 | { | |
a79c6551 | 86 | local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}" |
690d8824 JH |
87 | case "$cur" in |
88 | ?*:*) | |
a79c6551 SP |
89 | ref="${cur%%:*}" |
90 | cur="${cur#*:}" | |
690d8824 JH |
91 | case "$cur" in |
92 | ?*/*) | |
a79c6551 SP |
93 | pfx="${cur%/*}" |
94 | cur="${cur##*/}" | |
690d8824 JH |
95 | ls="$ref:$pfx" |
96 | pfx="$pfx/" | |
97 | ;; | |
98 | *) | |
99 | ls="$ref" | |
100 | ;; | |
101 | esac | |
102 | COMPREPLY=($(compgen -P "$pfx" \ | |
873537fa | 103 | -W "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \ |
690d8824 JH |
104 | | sed '/^100... blob /s,^.* ,, |
105 | /^040000 tree /{ | |
106 | s,^.* ,, | |
107 | s,$,/, | |
108 | } | |
109 | s/^.* //')" \ | |
110 | -- "$cur")) | |
111 | ;; | |
112 | *) | |
873537fa | 113 | COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur")) |
690d8824 JH |
114 | ;; |
115 | esac | |
116 | } | |
117 | ||
367dce2a DS |
118 | __git_aliases () |
119 | { | |
56fc25f2 | 120 | local i IFS=$'\n' |
873537fa | 121 | for i in $(git --git-dir="$(__gitdir)" repo-config --list); do |
56fc25f2 SP |
122 | case "$i" in |
123 | alias.*) | |
124 | i="${i#alias.}" | |
125 | echo "${i/=*/}" | |
126 | ;; | |
127 | esac | |
128 | done | |
367dce2a DS |
129 | } |
130 | ||
131 | __git_aliased_command () | |
132 | { | |
873537fa SP |
133 | local word cmdline=$(git --git-dir="$(__gitdir)" \ |
134 | repo-config --get "alias.$1") | |
367dce2a DS |
135 | for word in $cmdline; do |
136 | if [ "${word##-*}" ]; then | |
137 | echo $word | |
138 | return | |
139 | fi | |
140 | done | |
141 | } | |
142 | ||
690d8824 JH |
143 | _git_branch () |
144 | { | |
145 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
873537fa | 146 | COMPREPLY=($(compgen -W "-l -f -d -D $(__git_refs)" -- "$cur")) |
690d8824 JH |
147 | } |
148 | ||
149 | _git_cat_file () | |
150 | { | |
151 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
152 | case "${COMP_WORDS[0]},$COMP_CWORD" in | |
153 | git-cat-file*,1) | |
154 | COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur")) | |
155 | ;; | |
156 | git,2) | |
157 | COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur")) | |
158 | ;; | |
159 | *) | |
160 | __git_complete_file | |
161 | ;; | |
162 | esac | |
163 | } | |
164 | ||
165 | _git_checkout () | |
166 | { | |
167 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
873537fa | 168 | COMPREPLY=($(compgen -W "-l -b $(__git_refs)" -- "$cur")) |
690d8824 JH |
169 | } |
170 | ||
171 | _git_diff () | |
172 | { | |
173 | __git_complete_file | |
174 | } | |
175 | ||
176 | _git_diff_tree () | |
177 | { | |
178 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
873537fa | 179 | COMPREPLY=($(compgen -W "-r -p -M $(__git_refs)" -- "$cur")) |
690d8824 JH |
180 | } |
181 | ||
182 | _git_fetch () | |
183 | { | |
184 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
185 | ||
186 | case "${COMP_WORDS[0]},$COMP_CWORD" in | |
187 | git-fetch*,1) | |
188 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
189 | ;; | |
190 | git,2) | |
191 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
192 | ;; | |
193 | *) | |
194 | case "$cur" in | |
195 | *:*) | |
a79c6551 | 196 | cur="${cur#*:}" |
873537fa | 197 | COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur")) |
690d8824 JH |
198 | ;; |
199 | *) | |
200 | local remote | |
201 | case "${COMP_WORDS[0]}" in | |
202 | git-fetch) remote="${COMP_WORDS[1]}" ;; | |
203 | git) remote="${COMP_WORDS[2]}" ;; | |
204 | esac | |
205 | COMPREPLY=($(compgen -W "$(__git_refs2 "$remote")" -- "$cur")) | |
206 | ;; | |
207 | esac | |
208 | ;; | |
209 | esac | |
210 | } | |
211 | ||
212 | _git_ls_remote () | |
213 | { | |
214 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
215 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
216 | } | |
217 | ||
218 | _git_ls_tree () | |
219 | { | |
220 | __git_complete_file | |
221 | } | |
222 | ||
223 | _git_log () | |
224 | { | |
e5d5b21f | 225 | local pfx cur="${COMP_WORDS[COMP_CWORD]}" |
690d8824 | 226 | case "$cur" in |
e5d5b21f SP |
227 | *...*) |
228 | pfx="${cur%...*}..." | |
229 | cur="${cur#*...}" | |
230 | COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur")) | |
231 | ;; | |
690d8824 | 232 | *..*) |
e5d5b21f SP |
233 | pfx="${cur%..*}.." |
234 | cur="${cur#*..}" | |
873537fa | 235 | COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur")) |
690d8824 JH |
236 | ;; |
237 | *) | |
873537fa | 238 | COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur")) |
690d8824 JH |
239 | ;; |
240 | esac | |
241 | } | |
242 | ||
243 | _git_merge_base () | |
244 | { | |
245 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
873537fa | 246 | COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur")) |
690d8824 JH |
247 | } |
248 | ||
249 | _git_pull () | |
250 | { | |
251 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
252 | ||
253 | case "${COMP_WORDS[0]},$COMP_CWORD" in | |
254 | git-pull*,1) | |
255 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
256 | ;; | |
257 | git,2) | |
258 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
259 | ;; | |
260 | *) | |
261 | local remote | |
262 | case "${COMP_WORDS[0]}" in | |
263 | git-pull) remote="${COMP_WORDS[1]}" ;; | |
264 | git) remote="${COMP_WORDS[2]}" ;; | |
265 | esac | |
266 | COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur")) | |
267 | ;; | |
268 | esac | |
269 | } | |
270 | ||
271 | _git_push () | |
272 | { | |
273 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
274 | ||
275 | case "${COMP_WORDS[0]},$COMP_CWORD" in | |
276 | git-push*,1) | |
277 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
278 | ;; | |
279 | git,2) | |
280 | COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur")) | |
281 | ;; | |
282 | *) | |
283 | case "$cur" in | |
284 | *:*) | |
285 | local remote | |
286 | case "${COMP_WORDS[0]}" in | |
287 | git-push) remote="${COMP_WORDS[1]}" ;; | |
288 | git) remote="${COMP_WORDS[2]}" ;; | |
289 | esac | |
a79c6551 | 290 | cur="${cur#*:}" |
690d8824 JH |
291 | COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur")) |
292 | ;; | |
293 | *) | |
873537fa | 294 | COMPREPLY=($(compgen -W "$(__git_refs2)" -- "$cur")) |
690d8824 JH |
295 | ;; |
296 | esac | |
297 | ;; | |
298 | esac | |
299 | } | |
300 | ||
67e78c3b SP |
301 | _git_reset () |
302 | { | |
303 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
304 | local opt="--mixed --hard --soft" | |
873537fa | 305 | COMPREPLY=($(compgen -W "$opt $(__git_refs)" -- "$cur")) |
67e78c3b SP |
306 | } |
307 | ||
690d8824 JH |
308 | _git_show () |
309 | { | |
310 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
873537fa | 311 | COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur")) |
690d8824 JH |
312 | } |
313 | ||
314 | _git () | |
315 | { | |
873537fa SP |
316 | local i c=1 command __git_dir |
317 | ||
318 | while [ $c -lt $COMP_CWORD ]; do | |
319 | i="${COMP_WORDS[c]}" | |
320 | case "$i" in | |
321 | --git-dir=*) __git_dir="${i#--git-dir=}" ;; | |
322 | --bare) __git_dir="." ;; | |
323 | --version|--help|-p|--paginate) ;; | |
324 | *) command="$i"; break ;; | |
325 | esac | |
326 | c=$((++c)) | |
327 | done | |
328 | ||
329 | if [ $c -eq $COMP_CWORD -a -z "$command" ]; then | |
690d8824 | 330 | COMPREPLY=($(compgen \ |
873537fa SP |
331 | -W "--git-dir= --version \ |
332 | $(git help -a|egrep '^ ') \ | |
367dce2a | 333 | $(__git_aliases)" \ |
690d8824 | 334 | -- "${COMP_WORDS[COMP_CWORD]}")) |
873537fa SP |
335 | return; |
336 | fi | |
367dce2a | 337 | |
873537fa SP |
338 | local expansion=$(__git_aliased_command "$command") |
339 | [ "$expansion" ] && command="$expansion" | |
367dce2a | 340 | |
873537fa SP |
341 | case "$command" in |
342 | branch) _git_branch ;; | |
343 | cat-file) _git_cat_file ;; | |
344 | checkout) _git_checkout ;; | |
345 | diff) _git_diff ;; | |
346 | diff-tree) _git_diff_tree ;; | |
347 | fetch) _git_fetch ;; | |
348 | log) _git_log ;; | |
349 | ls-remote) _git_ls_remote ;; | |
350 | ls-tree) _git_ls_tree ;; | |
351 | merge-base) _git_merge_base ;; | |
352 | pull) _git_pull ;; | |
353 | push) _git_push ;; | |
354 | reset) _git_reset ;; | |
355 | show) _git_show ;; | |
356 | show-branch) _git_log ;; | |
357 | whatchanged) _git_log ;; | |
358 | *) COMPREPLY=() ;; | |
359 | esac | |
690d8824 JH |
360 | } |
361 | ||
362 | _gitk () | |
363 | { | |
364 | local cur="${COMP_WORDS[COMP_CWORD]}" | |
873537fa | 365 | COMPREPLY=($(compgen -W "--all $(__git_refs)" -- "$cur")) |
690d8824 JH |
366 | } |
367 | ||
368 | complete -o default -o nospace -F _git git | |
369 | complete -o default -F _gitk gitk | |
370 | complete -o default -F _git_branch git-branch | |
371 | complete -o default -o nospace -F _git_cat_file git-cat-file | |
372 | complete -o default -F _git_checkout git-checkout | |
373 | complete -o default -o nospace -F _git_diff git-diff | |
374 | complete -o default -F _git_diff_tree git-diff-tree | |
375 | complete -o default -o nospace -F _git_fetch git-fetch | |
376 | complete -o default -o nospace -F _git_log git-log | |
377 | complete -o default -F _git_ls_remote git-ls-remote | |
378 | complete -o default -o nospace -F _git_ls_tree git-ls-tree | |
379 | complete -o default -F _git_merge_base git-merge-base | |
380 | complete -o default -o nospace -F _git_pull git-pull | |
381 | complete -o default -o nospace -F _git_push git-push | |
67e78c3b | 382 | complete -o default -F _git_reset git-reset |
690d8824 | 383 | complete -o default -F _git_show git-show |
144d33de | 384 | complete -o default -o nospace -F _git_log git-show-branch |
690d8824 JH |
385 | complete -o default -o nospace -F _git_log git-whatchanged |
386 | ||
387 | # The following are necessary only for Cygwin, and only are needed | |
388 | # when the user has tab-completed the executable name and consequently | |
389 | # included the '.exe' suffix. | |
390 | # | |
76c3eb51 | 391 | if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then |
144d33de | 392 | complete -o default -o nospace -F _git git.exe |
dfb96092 | 393 | complete -o default -F _git_branch git-branch.exe |
690d8824 JH |
394 | complete -o default -o nospace -F _git_cat_file git-cat-file.exe |
395 | complete -o default -o nospace -F _git_diff git-diff.exe | |
396 | complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe | |
397 | complete -o default -o nospace -F _git_log git-log.exe | |
398 | complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe | |
399 | complete -o default -F _git_merge_base git-merge-base.exe | |
400 | complete -o default -o nospace -F _git_push git-push.exe | |
144d33de | 401 | complete -o default -o nospace -F _git_log git-show-branch.exe |
690d8824 | 402 | complete -o default -o nospace -F _git_log git-whatchanged.exe |
76c3eb51 | 403 | fi |