]> git.ipfire.org Git - thirdparty/git.git/blob - contrib/completion/git-completion.bash
Merge branch 'ml/completion-zsh'
[thirdparty/git.git] / contrib / completion / git-completion.bash
1 #!bash
2 #
3 # bash completion support for core Git.
4 #
5 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
6 # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
7 # Distributed under the GNU General Public License, version 2.0.
8 #
9 # The contained completion routines provide support for completing:
10 #
11 # *) local and remote branch names
12 # *) local and remote tag names
13 # *) .git/remotes file names
14 # *) git 'subcommands'
15 # *) tree paths within 'ref:path/to/file' expressions
16 # *) common --long-options
17 #
18 # To use these routines:
19 #
20 # 1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
21 # 2) Added the following line to your .bashrc:
22 # source ~/.git-completion.sh
23 #
24 # Or, add the following lines to your .zshrc:
25 # autoload bashcompinit
26 # bashcompinit
27 # source ~/.git-completion.sh
28 #
29 # 3) Consider changing your PS1 to also show the current branch:
30 # PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
31 #
32 # The argument to __git_ps1 will be displayed only if you
33 # are currently in a git repository. The %s token will be
34 # the name of the current branch.
35 #
36 # In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty
37 # value, unstaged (*) and staged (+) changes will be shown next
38 # to the branch name. You can configure this per-repository
39 # with the bash.showDirtyState variable, which defaults to true
40 # once GIT_PS1_SHOWDIRTYSTATE is enabled.
41 #
42 # You can also see if currently something is stashed, by setting
43 # GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
44 # then a '$' will be shown next to the branch name.
45 #
46 # If you would like to see if there're untracked files, then you can
47 # set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
48 # untracked files, then a '%' will be shown next to the branch name.
49 #
50 # If you would like to see the difference between HEAD and its
51 # upstream, set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates
52 # you are behind, ">" indicates you are ahead, and "<>"
53 # indicates you have diverged. You can further control
54 # behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated
55 # list of values:
56 # verbose show number of commits ahead/behind (+/-) upstream
57 # legacy don't use the '--count' option available in recent
58 # versions of git-rev-list
59 # git always compare HEAD to @{upstream}
60 # svn always compare HEAD to your SVN upstream
61 # By default, __git_ps1 will compare HEAD to your SVN upstream
62 # if it can find one, or @{upstream} otherwise. Once you have
63 # set GIT_PS1_SHOWUPSTREAM, you can override it on a
64 # per-repository basis by setting the bash.showUpstream config
65 # variable.
66 #
67 #
68 # To submit patches:
69 #
70 # *) Read Documentation/SubmittingPatches
71 # *) Send all patches to the current maintainer:
72 #
73 # "Shawn O. Pearce" <spearce@spearce.org>
74 #
75 # *) Always CC the Git mailing list:
76 #
77 # git@vger.kernel.org
78 #
79
80 case "$COMP_WORDBREAKS" in
81 *:*) : great ;;
82 *) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
83 esac
84
85 # __gitdir accepts 0 or 1 arguments (i.e., location)
86 # returns location of .git repo
87 __gitdir ()
88 {
89 if [ -z "${1-}" ]; then
90 if [ -n "${__git_dir-}" ]; then
91 echo "$__git_dir"
92 elif [ -d .git ]; then
93 echo .git
94 else
95 git rev-parse --git-dir 2>/dev/null
96 fi
97 elif [ -d "$1/.git" ]; then
98 echo "$1/.git"
99 else
100 echo "$1"
101 fi
102 }
103
104 # stores the divergence from upstream in $p
105 # used by GIT_PS1_SHOWUPSTREAM
106 __git_ps1_show_upstream ()
107 {
108 local key value
109 local svn_remote=() svn_url_pattern count n
110 local upstream=git legacy="" verbose=""
111
112 # get some config options from git-config
113 while read key value; do
114 case "$key" in
115 bash.showupstream)
116 GIT_PS1_SHOWUPSTREAM="$value"
117 if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
118 p=""
119 return
120 fi
121 ;;
122 svn-remote.*.url)
123 svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
124 svn_url_pattern+="\\|$value"
125 upstream=svn+git # default upstream is SVN if available, else git
126 ;;
127 esac
128 done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')
129
130 # parse configuration values
131 for option in ${GIT_PS1_SHOWUPSTREAM}; do
132 case "$option" in
133 git|svn) upstream="$option" ;;
134 verbose) verbose=1 ;;
135 legacy) legacy=1 ;;
136 esac
137 done
138
139 # Find our upstream
140 case "$upstream" in
141 git) upstream="@{upstream}" ;;
142 svn*)
143 # get the upstream from the "git-svn-id: ..." in a commit message
144 # (git-svn uses essentially the same procedure internally)
145 local svn_upstream=($(git log --first-parent -1 \
146 --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
147 if [[ 0 -ne ${#svn_upstream[@]} ]]; then
148 svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
149 svn_upstream=${svn_upstream%@*}
150 local n_stop="${#svn_remote[@]}"
151 for ((n=1; n <= n_stop; ++n)); do
152 svn_upstream=${svn_upstream#${svn_remote[$n]}}
153 done
154
155 if [[ -z "$svn_upstream" ]]; then
156 # default branch name for checkouts with no layout:
157 upstream=${GIT_SVN_ID:-git-svn}
158 else
159 upstream=${svn_upstream#/}
160 fi
161 elif [[ "svn+git" = "$upstream" ]]; then
162 upstream="@{upstream}"
163 fi
164 ;;
165 esac
166
167 # Find how many commits we are ahead/behind our upstream
168 if [[ -z "$legacy" ]]; then
169 count="$(git rev-list --count --left-right \
170 "$upstream"...HEAD 2>/dev/null)"
171 else
172 # produce equivalent output to --count for older versions of git
173 local commits
174 if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
175 then
176 local commit behind=0 ahead=0
177 for commit in $commits
178 do
179 case "$commit" in
180 "<"*) let ++behind
181 ;;
182 *) let ++ahead
183 ;;
184 esac
185 done
186 count="$behind $ahead"
187 else
188 count=""
189 fi
190 fi
191
192 # calculate the result
193 if [[ -z "$verbose" ]]; then
194 case "$count" in
195 "") # no upstream
196 p="" ;;
197 "0 0") # equal to upstream
198 p="=" ;;
199 "0 "*) # ahead of upstream
200 p=">" ;;
201 *" 0") # behind upstream
202 p="<" ;;
203 *) # diverged from upstream
204 p="<>" ;;
205 esac
206 else
207 case "$count" in
208 "") # no upstream
209 p="" ;;
210 "0 0") # equal to upstream
211 p=" u=" ;;
212 "0 "*) # ahead of upstream
213 p=" u+${count#0 }" ;;
214 *" 0") # behind upstream
215 p=" u-${count% 0}" ;;
216 *) # diverged from upstream
217 p=" u+${count#* }-${count% *}" ;;
218 esac
219 fi
220
221 }
222
223
224 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
225 # returns text to add to bash PS1 prompt (includes branch name)
226 __git_ps1 ()
227 {
228 local g="$(__gitdir)"
229 if [ -n "$g" ]; then
230 local r=""
231 local b=""
232 if [ -f "$g/rebase-merge/interactive" ]; then
233 r="|REBASE-i"
234 b="$(cat "$g/rebase-merge/head-name")"
235 elif [ -d "$g/rebase-merge" ]; then
236 r="|REBASE-m"
237 b="$(cat "$g/rebase-merge/head-name")"
238 else
239 if [ -d "$g/rebase-apply" ]; then
240 if [ -f "$g/rebase-apply/rebasing" ]; then
241 r="|REBASE"
242 elif [ -f "$g/rebase-apply/applying" ]; then
243 r="|AM"
244 else
245 r="|AM/REBASE"
246 fi
247 elif [ -f "$g/MERGE_HEAD" ]; then
248 r="|MERGING"
249 elif [ -f "$g/BISECT_LOG" ]; then
250 r="|BISECTING"
251 fi
252
253 b="$(git symbolic-ref HEAD 2>/dev/null)" || {
254
255 b="$(
256 case "${GIT_PS1_DESCRIBE_STYLE-}" in
257 (contains)
258 git describe --contains HEAD ;;
259 (branch)
260 git describe --contains --all HEAD ;;
261 (describe)
262 git describe HEAD ;;
263 (* | default)
264 git describe --exact-match HEAD ;;
265 esac 2>/dev/null)" ||
266
267 b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
268 b="unknown"
269 b="($b)"
270 }
271 fi
272
273 local w=""
274 local i=""
275 local s=""
276 local u=""
277 local c=""
278 local p=""
279
280 if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
281 if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
282 c="BARE:"
283 else
284 b="GIT_DIR!"
285 fi
286 elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
287 if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then
288 if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then
289 git diff --no-ext-diff --quiet --exit-code || w="*"
290 if git rev-parse --quiet --verify HEAD >/dev/null; then
291 git diff-index --cached --quiet HEAD -- || i="+"
292 else
293 i="#"
294 fi
295 fi
296 fi
297 if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
298 git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
299 fi
300
301 if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then
302 if [ -n "$(git ls-files --others --exclude-standard)" ]; then
303 u="%"
304 fi
305 fi
306
307 if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
308 __git_ps1_show_upstream
309 fi
310 fi
311
312 local f="$w$i$s$u"
313 printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
314 fi
315 }
316
317 # __gitcomp_1 requires 2 arguments
318 __gitcomp_1 ()
319 {
320 local c IFS=' '$'\t'$'\n'
321 for c in $1; do
322 case "$c$2" in
323 --*=*) printf %s$'\n' "$c$2" ;;
324 *.) printf %s$'\n' "$c$2" ;;
325 *) printf %s$'\n' "$c$2 " ;;
326 esac
327 done
328 }
329
330 # __gitcomp accepts 1, 2, 3, or 4 arguments
331 # generates completion reply with compgen
332 __gitcomp ()
333 {
334 local cur="${COMP_WORDS[COMP_CWORD]}"
335 if [ $# -gt 2 ]; then
336 cur="$3"
337 fi
338 case "$cur" in
339 --*=)
340 COMPREPLY=()
341 ;;
342 *)
343 local IFS=$'\n'
344 COMPREPLY=($(compgen -P "${2-}" \
345 -W "$(__gitcomp_1 "${1-}" "${4-}")" \
346 -- "$cur"))
347 ;;
348 esac
349 }
350
351 # __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
352 __git_heads ()
353 {
354 local cmd i is_hash=y dir="$(__gitdir "${1-}")"
355 if [ -d "$dir" ]; then
356 git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
357 refs/heads
358 return
359 fi
360 for i in $(git ls-remote "${1-}" 2>/dev/null); do
361 case "$is_hash,$i" in
362 y,*) is_hash=n ;;
363 n,*^{}) is_hash=y ;;
364 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
365 n,*) is_hash=y; echo "$i" ;;
366 esac
367 done
368 }
369
370 # __git_tags accepts 0 or 1 arguments (to pass to __gitdir)
371 __git_tags ()
372 {
373 local cmd i is_hash=y dir="$(__gitdir "${1-}")"
374 if [ -d "$dir" ]; then
375 git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
376 refs/tags
377 return
378 fi
379 for i in $(git ls-remote "${1-}" 2>/dev/null); do
380 case "$is_hash,$i" in
381 y,*) is_hash=n ;;
382 n,*^{}) is_hash=y ;;
383 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
384 n,*) is_hash=y; echo "$i" ;;
385 esac
386 done
387 }
388
389 # __git_refs accepts 0 or 1 arguments (to pass to __gitdir)
390 __git_refs ()
391 {
392 local i is_hash=y dir="$(__gitdir "${1-}")"
393 local cur="${COMP_WORDS[COMP_CWORD]}" format refs
394 if [ -d "$dir" ]; then
395 case "$cur" in
396 refs|refs/*)
397 format="refname"
398 refs="${cur%/*}"
399 ;;
400 *)
401 for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
402 if [ -e "$dir/$i" ]; then echo $i; fi
403 done
404 format="refname:short"
405 refs="refs/tags refs/heads refs/remotes"
406 ;;
407 esac
408 git --git-dir="$dir" for-each-ref --format="%($format)" \
409 $refs
410 return
411 fi
412 for i in $(git ls-remote "$dir" 2>/dev/null); do
413 case "$is_hash,$i" in
414 y,*) is_hash=n ;;
415 n,*^{}) is_hash=y ;;
416 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
417 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
418 n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
419 n,*) is_hash=y; echo "$i" ;;
420 esac
421 done
422 }
423
424 # __git_refs2 requires 1 argument (to pass to __git_refs)
425 __git_refs2 ()
426 {
427 local i
428 for i in $(__git_refs "$1"); do
429 echo "$i:$i"
430 done
431 }
432
433 # __git_refs_remotes requires 1 argument (to pass to ls-remote)
434 __git_refs_remotes ()
435 {
436 local cmd i is_hash=y
437 for i in $(git ls-remote "$1" 2>/dev/null); do
438 case "$is_hash,$i" in
439 n,refs/heads/*)
440 is_hash=y
441 echo "$i:refs/remotes/$1/${i#refs/heads/}"
442 ;;
443 y,*) is_hash=n ;;
444 n,*^{}) is_hash=y ;;
445 n,refs/tags/*) is_hash=y;;
446 n,*) is_hash=y; ;;
447 esac
448 done
449 }
450
451 __git_remotes ()
452 {
453 local i ngoff IFS=$'\n' d="$(__gitdir)"
454 shopt -q nullglob || ngoff=1
455 shopt -s nullglob
456 for i in "$d/remotes"/*; do
457 echo ${i#$d/remotes/}
458 done
459 [ "$ngoff" ] && shopt -u nullglob
460 for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
461 i="${i#remote.}"
462 echo "${i/.url*/}"
463 done
464 }
465
466 __git_list_merge_strategies ()
467 {
468 git merge -s help 2>&1 |
469 sed -n -e '/[Aa]vailable strategies are: /,/^$/{
470 s/\.$//
471 s/.*://
472 s/^[ ]*//
473 s/[ ]*$//
474 p
475 }'
476 }
477
478 __git_merge_strategies=
479 # 'git merge -s help' (and thus detection of the merge strategy
480 # list) fails, unfortunately, if run outside of any git working
481 # tree. __git_merge_strategies is set to the empty string in
482 # that case, and the detection will be repeated the next time it
483 # is needed.
484 __git_compute_merge_strategies ()
485 {
486 : ${__git_merge_strategies:=$(__git_list_merge_strategies)}
487 }
488
489 __git_complete_file ()
490 {
491 local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
492 case "$cur" in
493 ?*:*)
494 ref="${cur%%:*}"
495 cur="${cur#*:}"
496 case "$cur" in
497 ?*/*)
498 pfx="${cur%/*}"
499 cur="${cur##*/}"
500 ls="$ref:$pfx"
501 pfx="$pfx/"
502 ;;
503 *)
504 ls="$ref"
505 ;;
506 esac
507
508 case "$COMP_WORDBREAKS" in
509 *:*) : great ;;
510 *) pfx="$ref:$pfx" ;;
511 esac
512
513 local IFS=$'\n'
514 COMPREPLY=($(compgen -P "$pfx" \
515 -W "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \
516 | sed '/^100... blob /{
517 s,^.* ,,
518 s,$, ,
519 }
520 /^120000 blob /{
521 s,^.* ,,
522 s,$, ,
523 }
524 /^040000 tree /{
525 s,^.* ,,
526 s,$,/,
527 }
528 s/^.* //')" \
529 -- "$cur"))
530 ;;
531 *)
532 __gitcomp "$(__git_refs)"
533 ;;
534 esac
535 }
536
537 __git_complete_revlist ()
538 {
539 local pfx cur="${COMP_WORDS[COMP_CWORD]}"
540 case "$cur" in
541 *...*)
542 pfx="${cur%...*}..."
543 cur="${cur#*...}"
544 __gitcomp "$(__git_refs)" "$pfx" "$cur"
545 ;;
546 *..*)
547 pfx="${cur%..*}.."
548 cur="${cur#*..}"
549 __gitcomp "$(__git_refs)" "$pfx" "$cur"
550 ;;
551 *)
552 __gitcomp "$(__git_refs)"
553 ;;
554 esac
555 }
556
557 __git_complete_remote_or_refspec ()
558 {
559 local cmd="${COMP_WORDS[1]}"
560 local cur="${COMP_WORDS[COMP_CWORD]}"
561 local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
562 while [ $c -lt $COMP_CWORD ]; do
563 i="${COMP_WORDS[c]}"
564 case "$i" in
565 --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
566 --all)
567 case "$cmd" in
568 push) no_complete_refspec=1 ;;
569 fetch)
570 COMPREPLY=()
571 return
572 ;;
573 *) ;;
574 esac
575 ;;
576 -*) ;;
577 *) remote="$i"; break ;;
578 esac
579 c=$((++c))
580 done
581 if [ -z "$remote" ]; then
582 __gitcomp "$(__git_remotes)"
583 return
584 fi
585 if [ $no_complete_refspec = 1 ]; then
586 COMPREPLY=()
587 return
588 fi
589 [ "$remote" = "." ] && remote=
590 case "$cur" in
591 *:*)
592 case "$COMP_WORDBREAKS" in
593 *:*) : great ;;
594 *) pfx="${cur%%:*}:" ;;
595 esac
596 cur="${cur#*:}"
597 lhs=0
598 ;;
599 +*)
600 pfx="+"
601 cur="${cur#+}"
602 ;;
603 esac
604 case "$cmd" in
605 fetch)
606 if [ $lhs = 1 ]; then
607 __gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur"
608 else
609 __gitcomp "$(__git_refs)" "$pfx" "$cur"
610 fi
611 ;;
612 pull)
613 if [ $lhs = 1 ]; then
614 __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
615 else
616 __gitcomp "$(__git_refs)" "$pfx" "$cur"
617 fi
618 ;;
619 push)
620 if [ $lhs = 1 ]; then
621 __gitcomp "$(__git_refs)" "$pfx" "$cur"
622 else
623 __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
624 fi
625 ;;
626 esac
627 }
628
629 __git_complete_strategy ()
630 {
631 __git_compute_merge_strategies
632 case "${COMP_WORDS[COMP_CWORD-1]}" in
633 -s|--strategy)
634 __gitcomp "$__git_merge_strategies"
635 return 0
636 esac
637 local cur="${COMP_WORDS[COMP_CWORD]}"
638 case "$cur" in
639 --strategy=*)
640 __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
641 return 0
642 ;;
643 esac
644 return 1
645 }
646
647 __git_list_all_commands ()
648 {
649 local i IFS=" "$'\n'
650 for i in $(git help -a|egrep '^ [a-zA-Z0-9]')
651 do
652 case $i in
653 *--*) : helper pattern;;
654 *) echo $i;;
655 esac
656 done
657 }
658
659 __git_all_commands=
660 __git_compute_all_commands ()
661 {
662 : ${__git_all_commands:=$(__git_list_all_commands)}
663 }
664
665 __git_list_porcelain_commands ()
666 {
667 local i IFS=" "$'\n'
668 __git_compute_all_commands
669 for i in "help" $__git_all_commands
670 do
671 case $i in
672 *--*) : helper pattern;;
673 applymbox) : ask gittus;;
674 applypatch) : ask gittus;;
675 archimport) : import;;
676 cat-file) : plumbing;;
677 check-attr) : plumbing;;
678 check-ref-format) : plumbing;;
679 checkout-index) : plumbing;;
680 commit-tree) : plumbing;;
681 count-objects) : infrequent;;
682 cvsexportcommit) : export;;
683 cvsimport) : import;;
684 cvsserver) : daemon;;
685 daemon) : daemon;;
686 diff-files) : plumbing;;
687 diff-index) : plumbing;;
688 diff-tree) : plumbing;;
689 fast-import) : import;;
690 fast-export) : export;;
691 fsck-objects) : plumbing;;
692 fetch-pack) : plumbing;;
693 fmt-merge-msg) : plumbing;;
694 for-each-ref) : plumbing;;
695 hash-object) : plumbing;;
696 http-*) : transport;;
697 index-pack) : plumbing;;
698 init-db) : deprecated;;
699 local-fetch) : plumbing;;
700 lost-found) : infrequent;;
701 ls-files) : plumbing;;
702 ls-remote) : plumbing;;
703 ls-tree) : plumbing;;
704 mailinfo) : plumbing;;
705 mailsplit) : plumbing;;
706 merge-*) : plumbing;;
707 mktree) : plumbing;;
708 mktag) : plumbing;;
709 pack-objects) : plumbing;;
710 pack-redundant) : plumbing;;
711 pack-refs) : plumbing;;
712 parse-remote) : plumbing;;
713 patch-id) : plumbing;;
714 peek-remote) : plumbing;;
715 prune) : plumbing;;
716 prune-packed) : plumbing;;
717 quiltimport) : import;;
718 read-tree) : plumbing;;
719 receive-pack) : plumbing;;
720 reflog) : plumbing;;
721 remote-*) : transport;;
722 repo-config) : deprecated;;
723 rerere) : plumbing;;
724 rev-list) : plumbing;;
725 rev-parse) : plumbing;;
726 runstatus) : plumbing;;
727 sh-setup) : internal;;
728 shell) : daemon;;
729 show-ref) : plumbing;;
730 send-pack) : plumbing;;
731 show-index) : plumbing;;
732 ssh-*) : transport;;
733 stripspace) : plumbing;;
734 symbolic-ref) : plumbing;;
735 tar-tree) : deprecated;;
736 unpack-file) : plumbing;;
737 unpack-objects) : plumbing;;
738 update-index) : plumbing;;
739 update-ref) : plumbing;;
740 update-server-info) : daemon;;
741 upload-archive) : plumbing;;
742 upload-pack) : plumbing;;
743 write-tree) : plumbing;;
744 var) : infrequent;;
745 verify-pack) : infrequent;;
746 verify-tag) : plumbing;;
747 *) echo $i;;
748 esac
749 done
750 }
751
752 __git_porcelain_commands=
753 __git_compute_porcelain_commands ()
754 {
755 __git_compute_all_commands
756 : ${__git_porcelain_commands:=$(__git_list_porcelain_commands)}
757 }
758
759 __git_aliases ()
760 {
761 local i IFS=$'\n'
762 for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do
763 case "$i" in
764 alias.*)
765 i="${i#alias.}"
766 echo "${i/ */}"
767 ;;
768 esac
769 done
770 }
771
772 # __git_aliased_command requires 1 argument
773 __git_aliased_command ()
774 {
775 local word cmdline=$(git --git-dir="$(__gitdir)" \
776 config --get "alias.$1")
777 for word in $cmdline; do
778 case "$word" in
779 \!gitk|gitk)
780 echo "gitk"
781 return
782 ;;
783 \!*) : shell command alias ;;
784 -*) : option ;;
785 *=*) : setting env ;;
786 git) : git itself ;;
787 *)
788 echo "$word"
789 return
790 esac
791 done
792 }
793
794 # __git_find_on_cmdline requires 1 argument
795 __git_find_on_cmdline ()
796 {
797 local word subcommand c=1
798
799 while [ $c -lt $COMP_CWORD ]; do
800 word="${COMP_WORDS[c]}"
801 for subcommand in $1; do
802 if [ "$subcommand" = "$word" ]; then
803 echo "$subcommand"
804 return
805 fi
806 done
807 c=$((++c))
808 done
809 }
810
811 __git_has_doubledash ()
812 {
813 local c=1
814 while [ $c -lt $COMP_CWORD ]; do
815 if [ "--" = "${COMP_WORDS[c]}" ]; then
816 return 0
817 fi
818 c=$((++c))
819 done
820 return 1
821 }
822
823 __git_whitespacelist="nowarn warn error error-all fix"
824
825 _git_am ()
826 {
827 local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
828 if [ -d "$dir"/rebase-apply ]; then
829 __gitcomp "--skip --continue --resolved --abort"
830 return
831 fi
832 case "$cur" in
833 --whitespace=*)
834 __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
835 return
836 ;;
837 --*)
838 __gitcomp "
839 --3way --committer-date-is-author-date --ignore-date
840 --ignore-whitespace --ignore-space-change
841 --interactive --keep --no-utf8 --signoff --utf8
842 --whitespace= --scissors
843 "
844 return
845 esac
846 COMPREPLY=()
847 }
848
849 _git_apply ()
850 {
851 local cur="${COMP_WORDS[COMP_CWORD]}"
852 case "$cur" in
853 --whitespace=*)
854 __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
855 return
856 ;;
857 --*)
858 __gitcomp "
859 --stat --numstat --summary --check --index
860 --cached --index-info --reverse --reject --unidiff-zero
861 --apply --no-add --exclude=
862 --ignore-whitespace --ignore-space-change
863 --whitespace= --inaccurate-eof --verbose
864 "
865 return
866 esac
867 COMPREPLY=()
868 }
869
870 _git_add ()
871 {
872 __git_has_doubledash && return
873
874 local cur="${COMP_WORDS[COMP_CWORD]}"
875 case "$cur" in
876 --*)
877 __gitcomp "
878 --interactive --refresh --patch --update --dry-run
879 --ignore-errors --intent-to-add
880 "
881 return
882 esac
883 COMPREPLY=()
884 }
885
886 _git_archive ()
887 {
888 local cur="${COMP_WORDS[COMP_CWORD]}"
889 case "$cur" in
890 --format=*)
891 __gitcomp "$(git archive --list)" "" "${cur##--format=}"
892 return
893 ;;
894 --remote=*)
895 __gitcomp "$(__git_remotes)" "" "${cur##--remote=}"
896 return
897 ;;
898 --*)
899 __gitcomp "
900 --format= --list --verbose
901 --prefix= --remote= --exec=
902 "
903 return
904 ;;
905 esac
906 __git_complete_file
907 }
908
909 _git_bisect ()
910 {
911 __git_has_doubledash && return
912
913 local subcommands="start bad good skip reset visualize replay log run"
914 local subcommand="$(__git_find_on_cmdline "$subcommands")"
915 if [ -z "$subcommand" ]; then
916 __gitcomp "$subcommands"
917 return
918 fi
919
920 case "$subcommand" in
921 bad|good|reset|skip)
922 __gitcomp "$(__git_refs)"
923 ;;
924 *)
925 COMPREPLY=()
926 ;;
927 esac
928 }
929
930 _git_branch ()
931 {
932 local i c=1 only_local_ref="n" has_r="n"
933
934 while [ $c -lt $COMP_CWORD ]; do
935 i="${COMP_WORDS[c]}"
936 case "$i" in
937 -d|-m) only_local_ref="y" ;;
938 -r) has_r="y" ;;
939 esac
940 c=$((++c))
941 done
942
943 case "${COMP_WORDS[COMP_CWORD]}" in
944 --*)
945 __gitcomp "
946 --color --no-color --verbose --abbrev= --no-abbrev
947 --track --no-track --contains --merged --no-merged
948 --set-upstream
949 "
950 ;;
951 *)
952 if [ $only_local_ref = "y" -a $has_r = "n" ]; then
953 __gitcomp "$(__git_heads)"
954 else
955 __gitcomp "$(__git_refs)"
956 fi
957 ;;
958 esac
959 }
960
961 _git_bundle ()
962 {
963 local cmd="${COMP_WORDS[2]}"
964 case "$COMP_CWORD" in
965 2)
966 __gitcomp "create list-heads verify unbundle"
967 ;;
968 3)
969 # looking for a file
970 ;;
971 *)
972 case "$cmd" in
973 create)
974 __git_complete_revlist
975 ;;
976 esac
977 ;;
978 esac
979 }
980
981 _git_checkout ()
982 {
983 __git_has_doubledash && return
984
985 local cur="${COMP_WORDS[COMP_CWORD]}"
986 case "$cur" in
987 --conflict=*)
988 __gitcomp "diff3 merge" "" "${cur##--conflict=}"
989 ;;
990 --*)
991 __gitcomp "
992 --quiet --ours --theirs --track --no-track --merge
993 --conflict= --orphan --patch
994 "
995 ;;
996 *)
997 __gitcomp "$(__git_refs)"
998 ;;
999 esac
1000 }
1001
1002 _git_cherry ()
1003 {
1004 __gitcomp "$(__git_refs)"
1005 }
1006
1007 _git_cherry_pick ()
1008 {
1009 local cur="${COMP_WORDS[COMP_CWORD]}"
1010 case "$cur" in
1011 --*)
1012 __gitcomp "--edit --no-commit"
1013 ;;
1014 *)
1015 __gitcomp "$(__git_refs)"
1016 ;;
1017 esac
1018 }
1019
1020 _git_clean ()
1021 {
1022 __git_has_doubledash && return
1023
1024 local cur="${COMP_WORDS[COMP_CWORD]}"
1025 case "$cur" in
1026 --*)
1027 __gitcomp "--dry-run --quiet"
1028 return
1029 ;;
1030 esac
1031 COMPREPLY=()
1032 }
1033
1034 _git_clone ()
1035 {
1036 local cur="${COMP_WORDS[COMP_CWORD]}"
1037 case "$cur" in
1038 --*)
1039 __gitcomp "
1040 --local
1041 --no-hardlinks
1042 --shared
1043 --reference
1044 --quiet
1045 --no-checkout
1046 --bare
1047 --mirror
1048 --origin
1049 --upload-pack
1050 --template=
1051 --depth
1052 "
1053 return
1054 ;;
1055 esac
1056 COMPREPLY=()
1057 }
1058
1059 _git_commit ()
1060 {
1061 __git_has_doubledash && return
1062
1063 local cur="${COMP_WORDS[COMP_CWORD]}"
1064 case "$cur" in
1065 --cleanup=*)
1066 __gitcomp "default strip verbatim whitespace
1067 " "" "${cur##--cleanup=}"
1068 return
1069 ;;
1070 --reuse-message=*)
1071 __gitcomp "$(__git_refs)" "" "${cur##--reuse-message=}"
1072 return
1073 ;;
1074 --reedit-message=*)
1075 __gitcomp "$(__git_refs)" "" "${cur##--reedit-message=}"
1076 return
1077 ;;
1078 --untracked-files=*)
1079 __gitcomp "all no normal" "" "${cur##--untracked-files=}"
1080 return
1081 ;;
1082 --*)
1083 __gitcomp "
1084 --all --author= --signoff --verify --no-verify
1085 --edit --amend --include --only --interactive
1086 --dry-run --reuse-message= --reedit-message=
1087 --reset-author --file= --message= --template=
1088 --cleanup= --untracked-files --untracked-files=
1089 --verbose --quiet
1090 "
1091 return
1092 esac
1093 COMPREPLY=()
1094 }
1095
1096 _git_describe ()
1097 {
1098 local cur="${COMP_WORDS[COMP_CWORD]}"
1099 case "$cur" in
1100 --*)
1101 __gitcomp "
1102 --all --tags --contains --abbrev= --candidates=
1103 --exact-match --debug --long --match --always
1104 "
1105 return
1106 esac
1107 __gitcomp "$(__git_refs)"
1108 }
1109
1110 __git_diff_common_options="--stat --numstat --shortstat --summary
1111 --patch-with-stat --name-only --name-status --color
1112 --no-color --color-words --no-renames --check
1113 --full-index --binary --abbrev --diff-filter=
1114 --find-copies-harder
1115 --text --ignore-space-at-eol --ignore-space-change
1116 --ignore-all-space --exit-code --quiet --ext-diff
1117 --no-ext-diff
1118 --no-prefix --src-prefix= --dst-prefix=
1119 --inter-hunk-context=
1120 --patience
1121 --raw
1122 --dirstat --dirstat= --dirstat-by-file
1123 --dirstat-by-file= --cumulative
1124 "
1125
1126 _git_diff ()
1127 {
1128 __git_has_doubledash && return
1129
1130 local cur="${COMP_WORDS[COMP_CWORD]}"
1131 case "$cur" in
1132 --*)
1133 __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
1134 --base --ours --theirs --no-index
1135 $__git_diff_common_options
1136 "
1137 return
1138 ;;
1139 esac
1140 __git_complete_file
1141 }
1142
1143 __git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
1144 tkdiff vimdiff gvimdiff xxdiff araxis p4merge
1145 "
1146
1147 _git_difftool ()
1148 {
1149 __git_has_doubledash && return
1150
1151 local cur="${COMP_WORDS[COMP_CWORD]}"
1152 case "$cur" in
1153 --tool=*)
1154 __gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
1155 return
1156 ;;
1157 --*)
1158 __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
1159 --base --ours --theirs
1160 --no-renames --diff-filter= --find-copies-harder
1161 --relative --ignore-submodules
1162 --tool="
1163 return
1164 ;;
1165 esac
1166 __git_complete_file
1167 }
1168
1169 __git_fetch_options="
1170 --quiet --verbose --append --upload-pack --force --keep --depth=
1171 --tags --no-tags --all --prune --dry-run
1172 "
1173
1174 _git_fetch ()
1175 {
1176 local cur="${COMP_WORDS[COMP_CWORD]}"
1177 case "$cur" in
1178 --*)
1179 __gitcomp "$__git_fetch_options"
1180 return
1181 ;;
1182 esac
1183 __git_complete_remote_or_refspec
1184 }
1185
1186 _git_format_patch ()
1187 {
1188 local cur="${COMP_WORDS[COMP_CWORD]}"
1189 case "$cur" in
1190 --thread=*)
1191 __gitcomp "
1192 deep shallow
1193 " "" "${cur##--thread=}"
1194 return
1195 ;;
1196 --*)
1197 __gitcomp "
1198 --stdout --attach --no-attach --thread --thread=
1199 --output-directory
1200 --numbered --start-number
1201 --numbered-files
1202 --keep-subject
1203 --signoff --signature --no-signature
1204 --in-reply-to= --cc=
1205 --full-index --binary
1206 --not --all
1207 --cover-letter
1208 --no-prefix --src-prefix= --dst-prefix=
1209 --inline --suffix= --ignore-if-in-upstream
1210 --subject-prefix=
1211 "
1212 return
1213 ;;
1214 esac
1215 __git_complete_revlist
1216 }
1217
1218 _git_fsck ()
1219 {
1220 local cur="${COMP_WORDS[COMP_CWORD]}"
1221 case "$cur" in
1222 --*)
1223 __gitcomp "
1224 --tags --root --unreachable --cache --no-reflogs --full
1225 --strict --verbose --lost-found
1226 "
1227 return
1228 ;;
1229 esac
1230 COMPREPLY=()
1231 }
1232
1233 _git_gc ()
1234 {
1235 local cur="${COMP_WORDS[COMP_CWORD]}"
1236 case "$cur" in
1237 --*)
1238 __gitcomp "--prune --aggressive"
1239 return
1240 ;;
1241 esac
1242 COMPREPLY=()
1243 }
1244
1245 _git_gitk ()
1246 {
1247 _gitk
1248 }
1249
1250 _git_grep ()
1251 {
1252 __git_has_doubledash && return
1253
1254 local cur="${COMP_WORDS[COMP_CWORD]}"
1255 case "$cur" in
1256 --*)
1257 __gitcomp "
1258 --cached
1259 --text --ignore-case --word-regexp --invert-match
1260 --full-name
1261 --extended-regexp --basic-regexp --fixed-strings
1262 --files-with-matches --name-only
1263 --files-without-match
1264 --max-depth
1265 --count
1266 --and --or --not --all-match
1267 "
1268 return
1269 ;;
1270 esac
1271
1272 __gitcomp "$(__git_refs)"
1273 }
1274
1275 _git_help ()
1276 {
1277 local cur="${COMP_WORDS[COMP_CWORD]}"
1278 case "$cur" in
1279 --*)
1280 __gitcomp "--all --info --man --web"
1281 return
1282 ;;
1283 esac
1284 __git_compute_all_commands
1285 __gitcomp "$__git_all_commands
1286 attributes cli core-tutorial cvs-migration
1287 diffcore gitk glossary hooks ignore modules
1288 repository-layout tutorial tutorial-2
1289 workflows
1290 "
1291 }
1292
1293 _git_init ()
1294 {
1295 local cur="${COMP_WORDS[COMP_CWORD]}"
1296 case "$cur" in
1297 --shared=*)
1298 __gitcomp "
1299 false true umask group all world everybody
1300 " "" "${cur##--shared=}"
1301 return
1302 ;;
1303 --*)
1304 __gitcomp "--quiet --bare --template= --shared --shared="
1305 return
1306 ;;
1307 esac
1308 COMPREPLY=()
1309 }
1310
1311 _git_ls_files ()
1312 {
1313 __git_has_doubledash && return
1314
1315 local cur="${COMP_WORDS[COMP_CWORD]}"
1316 case "$cur" in
1317 --*)
1318 __gitcomp "--cached --deleted --modified --others --ignored
1319 --stage --directory --no-empty-directory --unmerged
1320 --killed --exclude= --exclude-from=
1321 --exclude-per-directory= --exclude-standard
1322 --error-unmatch --with-tree= --full-name
1323 --abbrev --ignored --exclude-per-directory
1324 "
1325 return
1326 ;;
1327 esac
1328 COMPREPLY=()
1329 }
1330
1331 _git_ls_remote ()
1332 {
1333 __gitcomp "$(__git_remotes)"
1334 }
1335
1336 _git_ls_tree ()
1337 {
1338 __git_complete_file
1339 }
1340
1341 # Options that go well for log, shortlog and gitk
1342 __git_log_common_options="
1343 --not --all
1344 --branches --tags --remotes
1345 --first-parent --merges --no-merges
1346 --max-count=
1347 --max-age= --since= --after=
1348 --min-age= --until= --before=
1349 "
1350 # Options that go well for log and gitk (not shortlog)
1351 __git_log_gitk_options="
1352 --dense --sparse --full-history
1353 --simplify-merges --simplify-by-decoration
1354 --left-right
1355 "
1356 # Options that go well for log and shortlog (not gitk)
1357 __git_log_shortlog_options="
1358 --author= --committer= --grep=
1359 --all-match
1360 "
1361
1362 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
1363 __git_log_date_formats="relative iso8601 rfc2822 short local default raw"
1364
1365 _git_log ()
1366 {
1367 __git_has_doubledash && return
1368
1369 local cur="${COMP_WORDS[COMP_CWORD]}"
1370 local g="$(git rev-parse --git-dir 2>/dev/null)"
1371 local merge=""
1372 if [ -f "$g/MERGE_HEAD" ]; then
1373 merge="--merge"
1374 fi
1375 case "$cur" in
1376 --pretty=*)
1377 __gitcomp "$__git_log_pretty_formats
1378 " "" "${cur##--pretty=}"
1379 return
1380 ;;
1381 --format=*)
1382 __gitcomp "$__git_log_pretty_formats
1383 " "" "${cur##--format=}"
1384 return
1385 ;;
1386 --date=*)
1387 __gitcomp "$__git_log_date_formats" "" "${cur##--date=}"
1388 return
1389 ;;
1390 --decorate=*)
1391 __gitcomp "long short" "" "${cur##--decorate=}"
1392 return
1393 ;;
1394 --*)
1395 __gitcomp "
1396 $__git_log_common_options
1397 $__git_log_shortlog_options
1398 $__git_log_gitk_options
1399 --root --topo-order --date-order --reverse
1400 --follow --full-diff
1401 --abbrev-commit --abbrev=
1402 --relative-date --date=
1403 --pretty= --format= --oneline
1404 --cherry-pick
1405 --graph
1406 --decorate --decorate=
1407 --walk-reflogs
1408 --parents --children
1409 $merge
1410 $__git_diff_common_options
1411 --pickaxe-all --pickaxe-regex
1412 "
1413 return
1414 ;;
1415 esac
1416 __git_complete_revlist
1417 }
1418
1419 __git_merge_options="
1420 --no-commit --no-stat --log --no-log --squash --strategy
1421 --commit --stat --no-squash --ff --no-ff --ff-only
1422 "
1423
1424 _git_merge ()
1425 {
1426 __git_complete_strategy && return
1427
1428 local cur="${COMP_WORDS[COMP_CWORD]}"
1429 case "$cur" in
1430 --*)
1431 __gitcomp "$__git_merge_options"
1432 return
1433 esac
1434 __gitcomp "$(__git_refs)"
1435 }
1436
1437 _git_mergetool ()
1438 {
1439 local cur="${COMP_WORDS[COMP_CWORD]}"
1440 case "$cur" in
1441 --tool=*)
1442 __gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
1443 return
1444 ;;
1445 --*)
1446 __gitcomp "--tool="
1447 return
1448 ;;
1449 esac
1450 COMPREPLY=()
1451 }
1452
1453 _git_merge_base ()
1454 {
1455 __gitcomp "$(__git_refs)"
1456 }
1457
1458 _git_mv ()
1459 {
1460 local cur="${COMP_WORDS[COMP_CWORD]}"
1461 case "$cur" in
1462 --*)
1463 __gitcomp "--dry-run"
1464 return
1465 ;;
1466 esac
1467 COMPREPLY=()
1468 }
1469
1470 _git_name_rev ()
1471 {
1472 __gitcomp "--tags --all --stdin"
1473 }
1474
1475 _git_notes ()
1476 {
1477 local subcommands="edit show"
1478 if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
1479 __gitcomp "$subcommands"
1480 return
1481 fi
1482
1483 case "${COMP_WORDS[COMP_CWORD-1]}" in
1484 -m|-F)
1485 COMPREPLY=()
1486 ;;
1487 *)
1488 __gitcomp "$(__git_refs)"
1489 ;;
1490 esac
1491 }
1492
1493 _git_pull ()
1494 {
1495 __git_complete_strategy && return
1496
1497 local cur="${COMP_WORDS[COMP_CWORD]}"
1498 case "$cur" in
1499 --*)
1500 __gitcomp "
1501 --rebase --no-rebase
1502 $__git_merge_options
1503 $__git_fetch_options
1504 "
1505 return
1506 ;;
1507 esac
1508 __git_complete_remote_or_refspec
1509 }
1510
1511 _git_push ()
1512 {
1513 local cur="${COMP_WORDS[COMP_CWORD]}"
1514 case "${COMP_WORDS[COMP_CWORD-1]}" in
1515 --repo)
1516 __gitcomp "$(__git_remotes)"
1517 return
1518 esac
1519 case "$cur" in
1520 --repo=*)
1521 __gitcomp "$(__git_remotes)" "" "${cur##--repo=}"
1522 return
1523 ;;
1524 --*)
1525 __gitcomp "
1526 --all --mirror --tags --dry-run --force --verbose
1527 --receive-pack= --repo=
1528 "
1529 return
1530 ;;
1531 esac
1532 __git_complete_remote_or_refspec
1533 }
1534
1535 _git_rebase ()
1536 {
1537 local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
1538 if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
1539 __gitcomp "--continue --skip --abort"
1540 return
1541 fi
1542 __git_complete_strategy && return
1543 case "$cur" in
1544 --whitespace=*)
1545 __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
1546 return
1547 ;;
1548 --*)
1549 __gitcomp "
1550 --onto --merge --strategy --interactive
1551 --preserve-merges --stat --no-stat
1552 --committer-date-is-author-date --ignore-date
1553 --ignore-whitespace --whitespace=
1554 --autosquash
1555 "
1556
1557 return
1558 esac
1559 __gitcomp "$(__git_refs)"
1560 }
1561
1562 __git_send_email_confirm_options="always never auto cc compose"
1563 __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
1564
1565 _git_send_email ()
1566 {
1567 local cur="${COMP_WORDS[COMP_CWORD]}"
1568 case "$cur" in
1569 --confirm=*)
1570 __gitcomp "
1571 $__git_send_email_confirm_options
1572 " "" "${cur##--confirm=}"
1573 return
1574 ;;
1575 --suppress-cc=*)
1576 __gitcomp "
1577 $__git_send_email_suppresscc_options
1578 " "" "${cur##--suppress-cc=}"
1579
1580 return
1581 ;;
1582 --smtp-encryption=*)
1583 __gitcomp "ssl tls" "" "${cur##--smtp-encryption=}"
1584 return
1585 ;;
1586 --*)
1587 __gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
1588 --compose --confirm= --dry-run --envelope-sender
1589 --from --identity
1590 --in-reply-to --no-chain-reply-to --no-signed-off-by-cc
1591 --no-suppress-from --no-thread --quiet
1592 --signed-off-by-cc --smtp-pass --smtp-server
1593 --smtp-server-port --smtp-encryption= --smtp-user
1594 --subject --suppress-cc= --suppress-from --thread --to
1595 --validate --no-validate"
1596 return
1597 ;;
1598 esac
1599 COMPREPLY=()
1600 }
1601
1602 _git_stage ()
1603 {
1604 _git_add
1605 }
1606
1607 __git_config_get_set_variables ()
1608 {
1609 local prevword word config_file= c=$COMP_CWORD
1610 while [ $c -gt 1 ]; do
1611 word="${COMP_WORDS[c]}"
1612 case "$word" in
1613 --global|--system|--file=*)
1614 config_file="$word"
1615 break
1616 ;;
1617 -f|--file)
1618 config_file="$word $prevword"
1619 break
1620 ;;
1621 esac
1622 prevword=$word
1623 c=$((--c))
1624 done
1625
1626 git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
1627 while read line
1628 do
1629 case "$line" in
1630 *.*=*)
1631 echo "${line/=*/}"
1632 ;;
1633 esac
1634 done
1635 }
1636
1637 _git_config ()
1638 {
1639 local cur="${COMP_WORDS[COMP_CWORD]}"
1640 local prv="${COMP_WORDS[COMP_CWORD-1]}"
1641 case "$prv" in
1642 branch.*.remote)
1643 __gitcomp "$(__git_remotes)"
1644 return
1645 ;;
1646 branch.*.merge)
1647 __gitcomp "$(__git_refs)"
1648 return
1649 ;;
1650 remote.*.fetch)
1651 local remote="${prv#remote.}"
1652 remote="${remote%.fetch}"
1653 __gitcomp "$(__git_refs_remotes "$remote")"
1654 return
1655 ;;
1656 remote.*.push)
1657 local remote="${prv#remote.}"
1658 remote="${remote%.push}"
1659 __gitcomp "$(git --git-dir="$(__gitdir)" \
1660 for-each-ref --format='%(refname):%(refname)' \
1661 refs/heads)"
1662 return
1663 ;;
1664 pull.twohead|pull.octopus)
1665 __git_compute_merge_strategies
1666 __gitcomp "$__git_merge_strategies"
1667 return
1668 ;;
1669 color.branch|color.diff|color.interactive|\
1670 color.showbranch|color.status|color.ui)
1671 __gitcomp "always never auto"
1672 return
1673 ;;
1674 color.pager)
1675 __gitcomp "false true"
1676 return
1677 ;;
1678 color.*.*)
1679 __gitcomp "
1680 normal black red green yellow blue magenta cyan white
1681 bold dim ul blink reverse
1682 "
1683 return
1684 ;;
1685 help.format)
1686 __gitcomp "man info web html"
1687 return
1688 ;;
1689 log.date)
1690 __gitcomp "$__git_log_date_formats"
1691 return
1692 ;;
1693 sendemail.aliasesfiletype)
1694 __gitcomp "mutt mailrc pine elm gnus"
1695 return
1696 ;;
1697 sendemail.confirm)
1698 __gitcomp "$__git_send_email_confirm_options"
1699 return
1700 ;;
1701 sendemail.suppresscc)
1702 __gitcomp "$__git_send_email_suppresscc_options"
1703 return
1704 ;;
1705 --get|--get-all|--unset|--unset-all)
1706 __gitcomp "$(__git_config_get_set_variables)"
1707 return
1708 ;;
1709 *.*)
1710 COMPREPLY=()
1711 return
1712 ;;
1713 esac
1714 case "$cur" in
1715 --*)
1716 __gitcomp "
1717 --global --system --file=
1718 --list --replace-all
1719 --get --get-all --get-regexp
1720 --add --unset --unset-all
1721 --remove-section --rename-section
1722 "
1723 return
1724 ;;
1725 branch.*.*)
1726 local pfx="${cur%.*}."
1727 cur="${cur##*.}"
1728 __gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur"
1729 return
1730 ;;
1731 branch.*)
1732 local pfx="${cur%.*}."
1733 cur="${cur#*.}"
1734 __gitcomp "$(__git_heads)" "$pfx" "$cur" "."
1735 return
1736 ;;
1737 guitool.*.*)
1738 local pfx="${cur%.*}."
1739 cur="${cur##*.}"
1740 __gitcomp "
1741 argprompt cmd confirm needsfile noconsole norescan
1742 prompt revprompt revunmerged title
1743 " "$pfx" "$cur"
1744 return
1745 ;;
1746 difftool.*.*)
1747 local pfx="${cur%.*}."
1748 cur="${cur##*.}"
1749 __gitcomp "cmd path" "$pfx" "$cur"
1750 return
1751 ;;
1752 man.*.*)
1753 local pfx="${cur%.*}."
1754 cur="${cur##*.}"
1755 __gitcomp "cmd path" "$pfx" "$cur"
1756 return
1757 ;;
1758 mergetool.*.*)
1759 local pfx="${cur%.*}."
1760 cur="${cur##*.}"
1761 __gitcomp "cmd path trustExitCode" "$pfx" "$cur"
1762 return
1763 ;;
1764 pager.*)
1765 local pfx="${cur%.*}."
1766 cur="${cur#*.}"
1767 __git_compute_all_commands
1768 __gitcomp "$__git_all_commands" "$pfx" "$cur"
1769 return
1770 ;;
1771 remote.*.*)
1772 local pfx="${cur%.*}."
1773 cur="${cur##*.}"
1774 __gitcomp "
1775 url proxy fetch push mirror skipDefaultUpdate
1776 receivepack uploadpack tagopt pushurl
1777 " "$pfx" "$cur"
1778 return
1779 ;;
1780 remote.*)
1781 local pfx="${cur%.*}."
1782 cur="${cur#*.}"
1783 __gitcomp "$(__git_remotes)" "$pfx" "$cur" "."
1784 return
1785 ;;
1786 url.*.*)
1787 local pfx="${cur%.*}."
1788 cur="${cur##*.}"
1789 __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur"
1790 return
1791 ;;
1792 esac
1793 __gitcomp "
1794 add.ignore-errors
1795 alias.
1796 apply.ignorewhitespace
1797 apply.whitespace
1798 branch.autosetupmerge
1799 branch.autosetuprebase
1800 clean.requireForce
1801 color.branch
1802 color.branch.current
1803 color.branch.local
1804 color.branch.plain
1805 color.branch.remote
1806 color.diff
1807 color.diff.commit
1808 color.diff.frag
1809 color.diff.meta
1810 color.diff.new
1811 color.diff.old
1812 color.diff.plain
1813 color.diff.whitespace
1814 color.grep
1815 color.grep.external
1816 color.grep.match
1817 color.interactive
1818 color.interactive.header
1819 color.interactive.help
1820 color.interactive.prompt
1821 color.pager
1822 color.showbranch
1823 color.status
1824 color.status.added
1825 color.status.changed
1826 color.status.header
1827 color.status.nobranch
1828 color.status.untracked
1829 color.status.updated
1830 color.ui
1831 commit.template
1832 core.autocrlf
1833 core.bare
1834 core.compression
1835 core.createObject
1836 core.deltaBaseCacheLimit
1837 core.editor
1838 core.excludesfile
1839 core.fileMode
1840 core.fsyncobjectfiles
1841 core.gitProxy
1842 core.ignoreCygwinFSTricks
1843 core.ignoreStat
1844 core.logAllRefUpdates
1845 core.loosecompression
1846 core.packedGitLimit
1847 core.packedGitWindowSize
1848 core.pager
1849 core.preferSymlinkRefs
1850 core.preloadindex
1851 core.quotepath
1852 core.repositoryFormatVersion
1853 core.safecrlf
1854 core.sharedRepository
1855 core.symlinks
1856 core.trustctime
1857 core.warnAmbiguousRefs
1858 core.whitespace
1859 core.worktree
1860 diff.autorefreshindex
1861 diff.external
1862 diff.mnemonicprefix
1863 diff.renameLimit
1864 diff.renameLimit.
1865 diff.renames
1866 diff.suppressBlankEmpty
1867 diff.tool
1868 diff.wordRegex
1869 difftool.
1870 difftool.prompt
1871 fetch.unpackLimit
1872 format.attach
1873 format.cc
1874 format.headers
1875 format.numbered
1876 format.pretty
1877 format.signature
1878 format.signoff
1879 format.subjectprefix
1880 format.suffix
1881 format.thread
1882 gc.aggressiveWindow
1883 gc.auto
1884 gc.autopacklimit
1885 gc.packrefs
1886 gc.pruneexpire
1887 gc.reflogexpire
1888 gc.reflogexpireunreachable
1889 gc.rerereresolved
1890 gc.rerereunresolved
1891 gitcvs.allbinary
1892 gitcvs.commitmsgannotation
1893 gitcvs.dbTableNamePrefix
1894 gitcvs.dbdriver
1895 gitcvs.dbname
1896 gitcvs.dbpass
1897 gitcvs.dbuser
1898 gitcvs.enabled
1899 gitcvs.logfile
1900 gitcvs.usecrlfattr
1901 guitool.
1902 gui.blamehistoryctx
1903 gui.commitmsgwidth
1904 gui.copyblamethreshold
1905 gui.diffcontext
1906 gui.encoding
1907 gui.fastcopyblame
1908 gui.matchtrackingbranch
1909 gui.newbranchtemplate
1910 gui.pruneduringfetch
1911 gui.spellingdictionary
1912 gui.trustmtime
1913 help.autocorrect
1914 help.browser
1915 help.format
1916 http.lowSpeedLimit
1917 http.lowSpeedTime
1918 http.maxRequests
1919 http.noEPSV
1920 http.proxy
1921 http.sslCAInfo
1922 http.sslCAPath
1923 http.sslCert
1924 http.sslKey
1925 http.sslVerify
1926 i18n.commitEncoding
1927 i18n.logOutputEncoding
1928 imap.folder
1929 imap.host
1930 imap.pass
1931 imap.port
1932 imap.preformattedHTML
1933 imap.sslverify
1934 imap.tunnel
1935 imap.user
1936 instaweb.browser
1937 instaweb.httpd
1938 instaweb.local
1939 instaweb.modulepath
1940 instaweb.port
1941 interactive.singlekey
1942 log.date
1943 log.showroot
1944 mailmap.file
1945 man.
1946 man.viewer
1947 merge.conflictstyle
1948 merge.log
1949 merge.renameLimit
1950 merge.stat
1951 merge.tool
1952 merge.verbosity
1953 mergetool.
1954 mergetool.keepBackup
1955 mergetool.prompt
1956 pack.compression
1957 pack.deltaCacheLimit
1958 pack.deltaCacheSize
1959 pack.depth
1960 pack.indexVersion
1961 pack.packSizeLimit
1962 pack.threads
1963 pack.window
1964 pack.windowMemory
1965 pager.
1966 pull.octopus
1967 pull.twohead
1968 push.default
1969 rebase.stat
1970 receive.denyCurrentBranch
1971 receive.denyDeletes
1972 receive.denyNonFastForwards
1973 receive.fsckObjects
1974 receive.unpackLimit
1975 repack.usedeltabaseoffset
1976 rerere.autoupdate
1977 rerere.enabled
1978 sendemail.aliasesfile
1979 sendemail.aliasesfiletype
1980 sendemail.bcc
1981 sendemail.cc
1982 sendemail.cccmd
1983 sendemail.chainreplyto
1984 sendemail.confirm
1985 sendemail.envelopesender
1986 sendemail.multiedit
1987 sendemail.signedoffbycc
1988 sendemail.smtpencryption
1989 sendemail.smtppass
1990 sendemail.smtpserver
1991 sendemail.smtpserverport
1992 sendemail.smtpuser
1993 sendemail.suppresscc
1994 sendemail.suppressfrom
1995 sendemail.thread
1996 sendemail.to
1997 sendemail.validate
1998 showbranch.default
1999 status.relativePaths
2000 status.showUntrackedFiles
2001 tar.umask
2002 transfer.unpackLimit
2003 url.
2004 user.email
2005 user.name
2006 user.signingkey
2007 web.browser
2008 branch. remote.
2009 "
2010 }
2011
2012 _git_remote ()
2013 {
2014 local subcommands="add rename rm show prune update set-head"
2015 local subcommand="$(__git_find_on_cmdline "$subcommands")"
2016 if [ -z "$subcommand" ]; then
2017 __gitcomp "$subcommands"
2018 return
2019 fi
2020
2021 case "$subcommand" in
2022 rename|rm|show|prune)
2023 __gitcomp "$(__git_remotes)"
2024 ;;
2025 update)
2026 local i c='' IFS=$'\n'
2027 for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do
2028 i="${i#remotes.}"
2029 c="$c ${i/ */}"
2030 done
2031 __gitcomp "$c"
2032 ;;
2033 *)
2034 COMPREPLY=()
2035 ;;
2036 esac
2037 }
2038
2039 _git_replace ()
2040 {
2041 __gitcomp "$(__git_refs)"
2042 }
2043
2044 _git_reset ()
2045 {
2046 __git_has_doubledash && return
2047
2048 local cur="${COMP_WORDS[COMP_CWORD]}"
2049 case "$cur" in
2050 --*)
2051 __gitcomp "--merge --mixed --hard --soft --patch"
2052 return
2053 ;;
2054 esac
2055 __gitcomp "$(__git_refs)"
2056 }
2057
2058 _git_revert ()
2059 {
2060 local cur="${COMP_WORDS[COMP_CWORD]}"
2061 case "$cur" in
2062 --*)
2063 __gitcomp "--edit --mainline --no-edit --no-commit --signoff"
2064 return
2065 ;;
2066 esac
2067 __gitcomp "$(__git_refs)"
2068 }
2069
2070 _git_rm ()
2071 {
2072 __git_has_doubledash && return
2073
2074 local cur="${COMP_WORDS[COMP_CWORD]}"
2075 case "$cur" in
2076 --*)
2077 __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
2078 return
2079 ;;
2080 esac
2081 COMPREPLY=()
2082 }
2083
2084 _git_shortlog ()
2085 {
2086 __git_has_doubledash && return
2087
2088 local cur="${COMP_WORDS[COMP_CWORD]}"
2089 case "$cur" in
2090 --*)
2091 __gitcomp "
2092 $__git_log_common_options
2093 $__git_log_shortlog_options
2094 --numbered --summary
2095 "
2096 return
2097 ;;
2098 esac
2099 __git_complete_revlist
2100 }
2101
2102 _git_show ()
2103 {
2104 __git_has_doubledash && return
2105
2106 local cur="${COMP_WORDS[COMP_CWORD]}"
2107 case "$cur" in
2108 --pretty=*)
2109 __gitcomp "$__git_log_pretty_formats
2110 " "" "${cur##--pretty=}"
2111 return
2112 ;;
2113 --format=*)
2114 __gitcomp "$__git_log_pretty_formats
2115 " "" "${cur##--format=}"
2116 return
2117 ;;
2118 --*)
2119 __gitcomp "--pretty= --format= --abbrev-commit --oneline
2120 $__git_diff_common_options
2121 "
2122 return
2123 ;;
2124 esac
2125 __git_complete_file
2126 }
2127
2128 _git_show_branch ()
2129 {
2130 local cur="${COMP_WORDS[COMP_CWORD]}"
2131 case "$cur" in
2132 --*)
2133 __gitcomp "
2134 --all --remotes --topo-order --current --more=
2135 --list --independent --merge-base --no-name
2136 --color --no-color
2137 --sha1-name --sparse --topics --reflog
2138 "
2139 return
2140 ;;
2141 esac
2142 __git_complete_revlist
2143 }
2144
2145 _git_stash ()
2146 {
2147 local cur="${COMP_WORDS[COMP_CWORD]}"
2148 local save_opts='--keep-index --no-keep-index --quiet --patch'
2149 local subcommands='save list show apply clear drop pop create branch'
2150 local subcommand="$(__git_find_on_cmdline "$subcommands")"
2151 if [ -z "$subcommand" ]; then
2152 case "$cur" in
2153 --*)
2154 __gitcomp "$save_opts"
2155 ;;
2156 *)
2157 if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then
2158 __gitcomp "$subcommands"
2159 else
2160 COMPREPLY=()
2161 fi
2162 ;;
2163 esac
2164 else
2165 case "$subcommand,$cur" in
2166 save,--*)
2167 __gitcomp "$save_opts"
2168 ;;
2169 apply,--*|pop,--*)
2170 __gitcomp "--index --quiet"
2171 ;;
2172 show,--*|drop,--*|branch,--*)
2173 COMPREPLY=()
2174 ;;
2175 show,*|apply,*|drop,*|pop,*|branch,*)
2176 __gitcomp "$(git --git-dir="$(__gitdir)" stash list \
2177 | sed -n -e 's/:.*//p')"
2178 ;;
2179 *)
2180 COMPREPLY=()
2181 ;;
2182 esac
2183 fi
2184 }
2185
2186 _git_submodule ()
2187 {
2188 __git_has_doubledash && return
2189
2190 local subcommands="add status init update summary foreach sync"
2191 if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
2192 local cur="${COMP_WORDS[COMP_CWORD]}"
2193 case "$cur" in
2194 --*)
2195 __gitcomp "--quiet --cached"
2196 ;;
2197 *)
2198 __gitcomp "$subcommands"
2199 ;;
2200 esac
2201 return
2202 fi
2203 }
2204
2205 _git_svn ()
2206 {
2207 local subcommands="
2208 init fetch clone rebase dcommit log find-rev
2209 set-tree commit-diff info create-ignore propget
2210 proplist show-ignore show-externals branch tag blame
2211 migrate mkdirs reset gc
2212 "
2213 local subcommand="$(__git_find_on_cmdline "$subcommands")"
2214 if [ -z "$subcommand" ]; then
2215 __gitcomp "$subcommands"
2216 else
2217 local remote_opts="--username= --config-dir= --no-auth-cache"
2218 local fc_opts="
2219 --follow-parent --authors-file= --repack=
2220 --no-metadata --use-svm-props --use-svnsync-props
2221 --log-window-size= --no-checkout --quiet
2222 --repack-flags --use-log-author --localtime
2223 --ignore-paths= $remote_opts
2224 "
2225 local init_opts="
2226 --template= --shared= --trunk= --tags=
2227 --branches= --stdlayout --minimize-url
2228 --no-metadata --use-svm-props --use-svnsync-props
2229 --rewrite-root= --prefix= --use-log-author
2230 --add-author-from $remote_opts
2231 "
2232 local cmt_opts="
2233 --edit --rmdir --find-copies-harder --copy-similarity=
2234 "
2235
2236 local cur="${COMP_WORDS[COMP_CWORD]}"
2237 case "$subcommand,$cur" in
2238 fetch,--*)
2239 __gitcomp "--revision= --fetch-all $fc_opts"
2240 ;;
2241 clone,--*)
2242 __gitcomp "--revision= $fc_opts $init_opts"
2243 ;;
2244 init,--*)
2245 __gitcomp "$init_opts"
2246 ;;
2247 dcommit,--*)
2248 __gitcomp "
2249 --merge --strategy= --verbose --dry-run
2250 --fetch-all --no-rebase --commit-url
2251 --revision $cmt_opts $fc_opts
2252 "
2253 ;;
2254 set-tree,--*)
2255 __gitcomp "--stdin $cmt_opts $fc_opts"
2256 ;;
2257 create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\
2258 show-externals,--*|mkdirs,--*)
2259 __gitcomp "--revision="
2260 ;;
2261 log,--*)
2262 __gitcomp "
2263 --limit= --revision= --verbose --incremental
2264 --oneline --show-commit --non-recursive
2265 --authors-file= --color
2266 "
2267 ;;
2268 rebase,--*)
2269 __gitcomp "
2270 --merge --verbose --strategy= --local
2271 --fetch-all --dry-run $fc_opts
2272 "
2273 ;;
2274 commit-diff,--*)
2275 __gitcomp "--message= --file= --revision= $cmt_opts"
2276 ;;
2277 info,--*)
2278 __gitcomp "--url"
2279 ;;
2280 branch,--*)
2281 __gitcomp "--dry-run --message --tag"
2282 ;;
2283 tag,--*)
2284 __gitcomp "--dry-run --message"
2285 ;;
2286 blame,--*)
2287 __gitcomp "--git-format"
2288 ;;
2289 migrate,--*)
2290 __gitcomp "
2291 --config-dir= --ignore-paths= --minimize
2292 --no-auth-cache --username=
2293 "
2294 ;;
2295 reset,--*)
2296 __gitcomp "--revision= --parent"
2297 ;;
2298 *)
2299 COMPREPLY=()
2300 ;;
2301 esac
2302 fi
2303 }
2304
2305 _git_tag ()
2306 {
2307 local i c=1 f=0
2308 while [ $c -lt $COMP_CWORD ]; do
2309 i="${COMP_WORDS[c]}"
2310 case "$i" in
2311 -d|-v)
2312 __gitcomp "$(__git_tags)"
2313 return
2314 ;;
2315 -f)
2316 f=1
2317 ;;
2318 esac
2319 c=$((++c))
2320 done
2321
2322 case "${COMP_WORDS[COMP_CWORD-1]}" in
2323 -m|-F)
2324 COMPREPLY=()
2325 ;;
2326 -*|tag)
2327 if [ $f = 1 ]; then
2328 __gitcomp "$(__git_tags)"
2329 else
2330 COMPREPLY=()
2331 fi
2332 ;;
2333 *)
2334 __gitcomp "$(__git_refs)"
2335 ;;
2336 esac
2337 }
2338
2339 _git_whatchanged ()
2340 {
2341 _git_log
2342 }
2343
2344 _git ()
2345 {
2346 local i c=1 command __git_dir
2347
2348 if [[ -n $ZSH_VERSION ]]; then
2349 emulate -L bash
2350 setopt KSH_TYPESET
2351 fi
2352
2353 while [ $c -lt $COMP_CWORD ]; do
2354 i="${COMP_WORDS[c]}"
2355 case "$i" in
2356 --git-dir=*) __git_dir="${i#--git-dir=}" ;;
2357 --bare) __git_dir="." ;;
2358 --version|-p|--paginate) ;;
2359 --help) command="help"; break ;;
2360 *) command="$i"; break ;;
2361 esac
2362 c=$((++c))
2363 done
2364
2365 if [ -z "$command" ]; then
2366 case "${COMP_WORDS[COMP_CWORD]}" in
2367 --*) __gitcomp "
2368 --paginate
2369 --no-pager
2370 --git-dir=
2371 --bare
2372 --version
2373 --exec-path
2374 --html-path
2375 --work-tree=
2376 --help
2377 "
2378 ;;
2379 *) __git_compute_porcelain_commands
2380 __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;;
2381 esac
2382 return
2383 fi
2384
2385 local completion_func="_git_${command//-/_}"
2386 declare -f $completion_func >/dev/null && $completion_func && return
2387
2388 local expansion=$(__git_aliased_command "$command")
2389 if [ -n "$expansion" ]; then
2390 completion_func="_git_${expansion//-/_}"
2391 declare -f $completion_func >/dev/null && $completion_func
2392 fi
2393 }
2394
2395 _gitk ()
2396 {
2397 if [[ -n $ZSH_VERSION ]]; then
2398 emulate -L bash
2399 setopt KSH_TYPESET
2400 fi
2401
2402 __git_has_doubledash && return
2403
2404 local cur="${COMP_WORDS[COMP_CWORD]}"
2405 local g="$(__gitdir)"
2406 local merge=""
2407 if [ -f "$g/MERGE_HEAD" ]; then
2408 merge="--merge"
2409 fi
2410 case "$cur" in
2411 --*)
2412 __gitcomp "
2413 $__git_log_common_options
2414 $__git_log_gitk_options
2415 $merge
2416 "
2417 return
2418 ;;
2419 esac
2420 __git_complete_revlist
2421 }
2422
2423 complete -o bashdefault -o default -o nospace -F _git git 2>/dev/null \
2424 || complete -o default -o nospace -F _git git
2425 complete -o bashdefault -o default -o nospace -F _gitk gitk 2>/dev/null \
2426 || complete -o default -o nospace -F _gitk gitk
2427
2428 # The following are necessary only for Cygwin, and only are needed
2429 # when the user has tab-completed the executable name and consequently
2430 # included the '.exe' suffix.
2431 #
2432 if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
2433 complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
2434 || complete -o default -o nospace -F _git git.exe
2435 fi
2436
2437 if [[ -n $ZSH_VERSION ]]; then
2438 shopt () {
2439 local option
2440 if [ $# -ne 2 ]; then
2441 echo "USAGE: $0 (-q|-s|-u) <option>" >&2
2442 return 1
2443 fi
2444 case "$2" in
2445 nullglob)
2446 option="$2"
2447 ;;
2448 *)
2449 echo "$0: invalid option: $2" >&2
2450 return 1
2451 esac
2452 case "$1" in
2453 -q) setopt | grep -q "$option" ;;
2454 -u) unsetopt "$option" ;;
2455 -s) setopt "$option" ;;
2456 *)
2457 echo "$0: invalid flag: $1" >&2
2458 return 1
2459 esac
2460 }
2461 fi