test-lib*.sh: set GIT_CEILING_DIRECTORIES
[topgit/pro.git] / contrib / tg-completion.bash
blobccda0774658fc2fa468808ac0fbd1ca83a75b361
2 # bash completion support for TopGit.
4 # Copyright (C) 2008 Jonas Fonseca <fonseca@diku.dk>
5 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
6 # Based git's git-completion.sh: http://repo.or.cz/w/git/fastimport.git
7 # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
8 # Distributed under the GNU General Public License, version 2.0.
10 # To use these routines:
12 # 1) Copy this file to somewhere (e.g. ~/.tg-completion.sh).
13 # 2) Source it from your ~/.bashrc.
15 # Note: Make sure the tg script is in your PATH before you source this
16 # script, so it can properly setup cached values.
18 case "$COMP_WORDBREAKS" in
19 *:*) : great ;;
20 *) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
21 esac
23 ### {{{ Utilities
25 __tgdir ()
27 if [ -z "$1" ]; then
28 if [ -n "$__tg_dir" ]; then
29 echo "$__tg_dir"
30 elif [ -d .git ]; then
31 echo .git
32 else
33 git rev-parse --git-dir 2>/dev/null
35 elif [ -d "$1/.git" ]; then
36 echo "$1/.git"
37 else
38 echo "$1"
42 __tgcomp_1 ()
44 local c IFS=' '$'\t'$'\n'
45 for c in $1; do
46 case "$c$2" in
47 --*=*) printf %s$'\n' "$c$2" ;;
48 *.) printf %s$'\n' "$c$2" ;;
49 *) printf %s$'\n' "$c$2 " ;;
50 esac
51 done
54 __tgcomp ()
56 local cur="${COMP_WORDS[COMP_CWORD]}"
57 if [ $# -gt 2 ]; then
58 cur="$3"
60 case "$cur" in
61 --*=)
62 COMPREPLY=()
65 local IFS=$'\n'
66 COMPREPLY=($(compgen -P "$2" \
67 -W "$(__tgcomp_1 "$1" "$4")" \
68 -- "$cur"))
70 esac
73 __tg_heads ()
75 local cmd i is_hash=y dir="$(__tgdir "$1")"
76 if [ -d "$dir" ]; then
77 git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
78 refs/heads
79 return
81 for i in $(git ls-remote "$1" 2>/dev/null); do
82 case "$is_hash,$i" in
83 y,*) is_hash=n ;;
84 n,*^{}) is_hash=y ;;
85 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
86 n,*) is_hash=y; echo "$i" ;;
87 esac
88 done
91 __tg_refs ()
93 local cmd i is_hash=y dir="$(__tgdir "$1")"
94 if [ -d "$dir" ]; then
95 if [ -e "$dir/HEAD" ]; then echo HEAD; fi
96 git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
97 refs/tags refs/heads refs/remotes
98 return
100 for i in $(git ls-remote "$dir" 2>/dev/null); do
101 case "$is_hash,$i" in
102 y,*) is_hash=n ;;
103 n,*^{}) is_hash=y ;;
104 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
105 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
106 n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
107 n,*) is_hash=y; echo "$i" ;;
108 esac
109 done
112 __tg_refs2 ()
114 local i
115 for i in $(__tg_refs "$1"); do
116 echo "$i:$i"
117 done
120 __tg_refs_remotes ()
122 local cmd i is_hash=y
123 for i in $(git ls-remote "$1" 2>/dev/null); do
124 case "$is_hash,$i" in
125 n,refs/heads/*)
126 is_hash=y
127 echo "$i:refs/remotes/$1/${i#refs/heads/}"
129 y,*) is_hash=n ;;
130 n,*^{}) is_hash=y ;;
131 n,refs/tags/*) is_hash=y;;
132 n,*) is_hash=y; ;;
133 esac
134 done
137 __tg_remotes ()
139 local i ngoff IFS=$'\n' d="$(__tgdir)"
140 shopt -q nullglob || ngoff=1
141 shopt -s nullglob
142 for i in "$d/remotes"/*; do
143 echo ${i#$d/remotes/}
144 done
145 [ "$ngoff" ] && shopt -u nullglob
146 for i in $(git --git-dir="$d" config --list); do
147 case "$i" in
148 remote.*.url=*)
149 i="${i#remote.}"
150 echo "${i/.url=*/}"
152 esac
153 done
156 __tg_find_subcommand ()
158 local word subcommand c=1
160 while [ $c -lt $COMP_CWORD ]; do
161 word="${COMP_WORDS[c]}"
162 for subcommand in $1; do
163 if [ "$subcommand" = "$word" ]; then
164 echo "$subcommand"
165 return
167 done
168 c=$((++c))
169 done
172 __tg_complete_revlist ()
174 local pfx cur="${COMP_WORDS[COMP_CWORD]}"
175 case "$cur" in
176 *...*)
177 pfx="${cur%...*}..."
178 cur="${cur#*...}"
179 __tgcomp "$(__tg_refs)" "$pfx" "$cur"
181 *..*)
182 pfx="${cur%..*}.."
183 cur="${cur#*..}"
184 __tgcomp "$(__tg_refs)" "$pfx" "$cur"
187 __tgcomp "$(__tg_refs)"
189 esac
192 __tg_topics ()
194 tg summary -t
197 __tg_commands ()
199 if [ -n "$__tg_all_commandlist" ]; then
200 echo "$__tg_all_commandlist"
201 return
203 local i IFS=" "$'\n'
204 for i in $(tg help | sed -n 's/^Usage:.*(\([^)]*\)).*/\1/p' | tr '|' ' ')
206 case $i in
207 *--*) : helper pattern;;
208 *) echo $i;;
209 esac
210 done
211 echo help
213 __tg_all_commandlist=
214 __tg_all_commandlist="$(__tg_commands 2>/dev/null)"
216 __tg_complete_arg ()
218 if [ $COMP_CWORD -gt 2 ] && [ "${COMP_WORDS[$COMP_CWORD - 1]}" = "$1" ]; then
219 return 0
221 return 1
224 ### }}}
225 ### {{{ Commands
227 _tg_create ()
229 local cmd="$1"
230 local cur="${COMP_WORDS[COMP_CWORD]}"
232 # Name must be the first arg after the create command
233 if [ $((cmd + 1)) = $COMP_CWORD ]; then
234 __tgcomp "$(__tg_topics)"
235 return
238 __tg_complete_arg "-r" && {
239 __tgcomp "$(__tg_remotes)"
240 return
243 case "$cur" in
245 __tgcomp "
250 __tgcomp "$(__tg_refs)"
251 esac
254 _tg_delete ()
256 local cur="${COMP_WORDS[COMP_CWORD]}"
258 case "$cur" in
260 __tgcomp "
265 __tgcomp "$(__tg_topics)"
266 esac
269 _tg_depend ()
271 local subcommands="add"
272 local subcommand="$(__git_find_subcommand "$subcommands" 2>/dev/null || __git_find_on_cmdline "$subcommands" 2>/dev/null)"
273 if [ -z "$subcommand" ]; then
274 __tgcomp "$subcommands"
275 return
278 case "$subcommand" in
279 add)
280 __tgcomp "$(__tg_refs)"
281 esac
284 _tg_export ()
286 local cur="${COMP_WORDS[COMP_CWORD]}"
288 __tg_complete_arg "--collapse" && {
289 __tgcomp "$(__tg_heads)"
290 return
293 __tg_complete_arg "--quilt" && {
294 return
297 case "$cur" in
299 __tgcomp "
300 --collapse
301 --quilt
303 esac
306 _tg_help ()
308 local cur="${COMP_WORDS[COMP_CWORD]}"
309 case "$cur" in
311 COMPREPLY=()
312 return
314 esac
315 __tgcomp "$(__tg_commands)"
318 _tg_import ()
320 local cur="${COMP_WORDS[COMP_CWORD]}"
322 __tg_complete_arg "-p" && {
323 COMPREPLY=()
324 return
327 case "$cur" in
329 __tgcomp "
334 __tg_complete_revlist
335 esac
338 _tg_info ()
340 local cur="${COMP_WORDS[COMP_CWORD]}"
342 case "$cur" in
344 __tgcomp "$(__tg_topics)"
345 esac
348 _tg_log ()
350 local cur="${COMP_WORDS[COMP_CWORD]}"
352 case "$cur" in
354 __tgcomp "$(__tg_topics)"
355 esac
358 _tg_mail ()
360 local cur="${COMP_WORDS[COMP_CWORD]}"
362 case "$cur" in
364 __tgcomp "
372 __tgcomp "$(__tg_topics)"
373 esac
376 _tg_patch ()
378 local cur="${COMP_WORDS[COMP_CWORD]}"
380 case "$cur" in
382 __tgcomp "
388 __tgcomp "$(__tg_topics)"
389 esac
392 _tg_push ()
394 local cur="${COMP_WORDS[COMP_CWORD]}"
396 __tg_complete_arg "-r" && {
397 __tgcomp "$(__tg_remotes)"
398 return
401 case "$cur" in
403 __tgcomp "
404 --no-deps
405 --dry-run
406 --tgish-only
411 __tgcomp "$(__tg_topics)"
412 esac
415 _tg_remote ()
417 local cur="${COMP_WORDS[COMP_CWORD]}"
419 case "$cur" in
421 __tgcomp "
422 --populate
426 __tgcomp "$(__tg_remotes)"
427 esac
430 _tg_summary ()
432 local cur="${COMP_WORDS[COMP_CWORD]}"
434 case "$cur" in
436 __tgcomp "
437 --graphviz
438 --sort
439 --deps
444 esac
447 _tg_update ()
449 local cur="${COMP_WORDS[COMP_CWORD]}"
451 case "$cur" in
453 __tgcomp "$(__tg_topics)"
454 esac
457 _tg_next ()
459 local cur="${COMP_WORDS[COMP_CWORD]}"
461 case "$cur" in
463 __tgcomp "
469 __tgcomp "$(__tg_heads)"
470 esac
473 _tg_prev ()
475 local cur="${COMP_WORDS[COMP_CWORD]}"
477 case "$cur" in
479 __tgcomp "
485 __tgcomp "$(__tg_topics)"
486 esac
489 ### }}}
490 ### {{{ tg completion
492 _tg ()
494 local i c=1 command __tg_dir
496 while [ $c -lt $COMP_CWORD ]; do
497 i="${COMP_WORDS[c]}"
498 case "$i" in
499 -r)
500 c=$((++c))
501 if [ $c -lt $COMP_CWORD ]; then
502 __tgcomp "$(__tg_remotes)"
503 return
506 -h|--help) command="help"; break ;;
507 *) command="$i"; break ;;
508 esac
509 c=$((++c))
510 done
512 if [ -z "$command" ]; then
513 case "${COMP_WORDS[COMP_CWORD]}" in
514 -*) __tgcomp "
517 --help
520 *) __tgcomp "$(__tg_commands)" ;;
521 esac
522 return
525 case "$command" in
526 create) _tg_create "$c" ;;
527 delete) _tg_delete ;;
528 depend) _tg_depend ;;
529 export) _tg_export ;;
530 files) _tg_patch ;;
531 help) _tg_help ;;
532 import) _tg_import ;;
533 info) _tg_info ;;
534 log) _tg_log ;;
535 mail) _tg_mail ;;
536 next) _tg_next ;;
537 patch) _tg_patch ;;
538 prev) _tg_prev ;;
539 push) _tg_push ;;
540 remote) _tg_remote ;;
541 summary) _tg_summary ;;
542 update) _tg_update ;;
543 *) COMPREPLY=() ;;
544 esac
547 ### }}}
549 complete -o default -o nospace -F _tg tg
551 # The following are necessary only for Cygwin, and only are needed
552 # when the user has tab-completed the executable name and consequently
553 # included the '.exe' suffix.
555 if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
556 complete -o default -o nospace -F _tg tg.exe