Zsh complete all patches for stg refresh -p
[stgit.git] / completion / stgit.zsh
blobbbcf1f52bb9e06430cd08c989a5923081ab64c53
1 #compdef stg
3 # This script implements zsh completions for StGit (stg).
5 # To use these completions, copy to a directory in $fpath as _stgit.
6 # For example:
8 # $ mkdir ~/.zsh.d
9 # $ cp completion/stgit.zsh ~/.zsh.d/_stgit
10 # $ $EDITOR ~/.zshrc
12 # fpath=("$HOME/.zsh.d" $fpath)
13 # autoload -U compinit
16 _stg-branch() {
17 __stg_add_args_help
18 subcmd_args+=(
19 - group-list
20 '--list[list branches]'
21 - group-switch
22 '--merge[merge worktree changes into other branch]'
23 ':branch:__stg_branch_stgit'
24 - group-create
25 '--create[create and switch to new branch]'
26 ':new-branch:'
27 ':committish:'
28 - group-clone
29 '--clone[clone current branch to new branch]'
30 ':new-branch:'
31 - group-rename
32 '(-r --rename)'{-r,--rename}'[rename existing branch]'
33 ':branch:__stg_branch_stgit'
34 ':new-branch:'
35 - group-protect
36 '(-p --protect)'{-p,--protect}'[prevent stg from modifying branch]'
37 ':branch:__stg_branch_stgit'
38 - group-unprotect
39 '(-u --unprotect)'{-u,--unprotect}'[allow stg to modify branch]'
40 ':branch:__stg_branch_stgit'
41 - group-delete
42 '--delete[delete branch]'
43 '--force[force delete when series is non-empty]'
44 ':branch:__stg_branch_stgit'
45 - group-cleanup
46 '--cleanup[cleanup stg metadata for branch]'
47 '--force[force cleanup when series is non-empty]'
48 ':branch:__stg_branch_stgit'
49 - group-description
50 '(-d --description)'{-d,--description}'[set branch description]:description'
51 ':branch:__stg_branch_stgit'
53 _arguments -s -S $subcmd_args
56 _stg-clean() {
57 __stg_add_args_help
58 subcmd_args+=(
59 '(-a --applied)'{-a,--applied}'[delete empty applied patches]'
60 '(-u --unapplied)'{-u,--unapplied}'[delete empty unapplied patches]'
62 _arguments -s -S $subcmd_args
65 _stg-clone() {
66 __stg_add_args_help
67 subcmd_args+=(
68 ':repository:'
69 ': :_directories'
71 _arguments -s $subcmd_args
74 _stg-commit() {
75 __stg_add_args_help
76 subcmd_args+=(
77 '--allow-empty[allow committing empty patches]'
78 - group-all
79 '(-a --all)'{-a,--all}'[commit all unapplied patches]'
80 - group-number
81 '(-n --number)'{-n+,--number=}'[commit specified number of patches]:number'
82 - group-patches
83 '*:applied patches:__stg_patches_applied'
85 _arguments -s -S $subcmd_args
88 _stg-delete() {
89 __stg_add_args_help
90 __stg_add_args_branch
91 subcmd_args+=(
92 '--spill[spill patch contents to worktree and index]'
93 - group-top
94 '(-t --top)'{-t,--top}'[delete top patch]'
95 - group-patchnames
96 '*:patches:__stg_patches_all'
98 _arguments -s -S $subcmd_args
101 _stg-diff() {
102 __stg_add_args_help
103 __stg_add_args_diffopts
104 subcmd_args+=(
105 '(-r --range)'{-r,--range=}'[show diff between revisions]: :__stg_patches_all'
106 '(-s --stat)'{-s,--stat}'[show stat instead of diff]'
107 '*:files:__stg_changed_files'
109 _arguments -s -S $subcmd_args
112 _stg-edit() {
113 __stg_add_args_help
114 __stg_add_args_author
115 __stg_add_args_diffopts
116 __stg_add_args_edit
117 __stg_add_args_hook
118 __stg_add_args_savetemplate
119 __stg_add_args_sign
120 subcmd_args+=(
121 '(-d --diff)'{-d,--diff}'[edit patch diff]'
122 '(-t --set-tree)'{-t,--set-tree=}'[set git tree of patch]:treeish'
123 ':patch:__stg_patches_all'
125 __stg_add_args_message
126 _arguments -s -S $subcmd_args
129 _stg-export() {
130 __stg_add_args_help
131 __stg_add_args_branch
132 __stg_add_args_diffopts
133 subcmd_args+=(
134 '(-d --dir)'{-d,--dir}'[export patches to directory]: :_directories'
135 '(-n --numbered)'{-n,--numbered}'[prefix patch names with order numbers]'
136 '(-s --stdout)'{-s,--stdout}'[dump patches to standard output]'
137 '(-t --template)'{-t,--template=}'[use template file]: :_files'
138 '*:patches:__stg_patches_unhidden'
139 + '(suffix)'
140 '(-e --extension)'{-e,--extension=}'[extension to append to patch names]:extension'
141 '(-p --patch)'{-p,--patch}'[append .patch to patch names]'
143 _arguments -s -S $subcmd_args
146 _stg-files() {
147 __stg_add_args_help
148 __stg_add_args_diffopts
149 subcmd_args+=(
150 '--bare[bare file names]'
151 '(-s --stat)'{-s,--stat}'[show diff stat]'
152 ':patches:__stg_patches_all'
154 _arguments -s -S $subcmd_args
157 _stg-float() {
158 __stg_add_args_help
159 __stg_add_args_keep
160 subcmd_args+=(
161 '--noapply[Reorder patches by floating without applying]'
162 '(-s --series)'{-s,--series=}'[arrange according to series file]: :_files'
163 '*:patches:__stg_patches_all'
165 _arguments -s -S $subcmd_args
168 _stg-fold() {
169 __stg_add_args_help
170 subcmd_args+=(
171 '(-b --base)'{-b,--base=}'[apply on base commit instead of HEAD]:commit'
172 '(-p --strip)'{-p+,--strip=}'[remove N leading directories from diff paths]:num'
173 '-C=[ensure N lines of surrounding context for each change]:num'
174 '--reject[leave rejected hunks in .rej files]'
175 ':file:_files'
177 _arguments -s -S $subcmd_args
180 _stg-goto() {
181 __stg_add_args_help
182 __stg_add_args_keep
183 __stg_add_args_merged
184 subcmd_args+=(
185 ':patches:__stg_patches_all'
187 _arguments -s -S $subcmd_args
190 _stg-help() {
191 _arguments -s ':commands:__stg_subcommands'
194 _stg-hide() {
195 __stg_add_args_help
196 __stg_add_args_branch
197 subcmd_args+=(
198 ':patches:__stg_patches_unhidden'
200 _arguments -s -S $subcmd_args
203 _stg-id() {
204 __stg_add_args_help
205 subcmd_args+=(
206 ':references:__stg_patches_all'
208 _arguments -s -S $subcmd_args
211 _stg-import() {
212 __stg_add_args_help
213 __stg_add_args_author
214 __stg_add_args_edit
215 __stg_add_args_sign
216 subcmd_args+=(
217 '(-n --name)'{-n,--name}'[name for imported patch]'
218 '(-p --strip)'{-p+,--strip=}'[remove N leading directories from diff paths]:num'
219 '(-t --stripname)'{-t,--stripname}'[strip number and extension from patch name]'
220 '-C=[ensure N lines of surrounding context for each change]:num'
221 '(-i --ignore)'{-i,--ignore}'[ingore applied patches in series]'
222 '--replace[replace unapplied patches in series]'
223 '--reject[leave rejected hunks in .rej files]'
224 '--keep-cr[do not remove CR from email lines ending with CRLF]'
225 '--message-id[create Message-Id trailer from email header]'
226 '(-d --showdiff)'{-d,--showdiff}'[show patch content in editor buffer]'
227 ':file:_files'
228 + '(source)'
229 '(-m --mail)'{-m,--mail}'[import from standard email file]'
230 '(-M --mbox)'{-M,--mbox}'[import from mbox file]'
231 '(-s --series)'{-s,--series}'[import from series file]'
232 '(-u --url)'{-u,--url}'[import patch from URL]'
234 _arguments -s -S $subcmd_args
237 _stg-init() {
238 __stg_add_args_help
239 _arguments -s $subcmd_args
242 _stg-log() {
243 __stg_add_args_help
244 __stg_add_args_branch
245 subcmd_args+=(
246 '--clear[clear log history]'
247 '(-d --diff)'{-d,--diff}'[show refresh diffs]'
248 '(-f --full)'{-f,--full}'[show full commit ids]'
249 '(-g --graphical)'{-g,--graphical}'[show log in gitk]'
250 '(-n --number)'{-n+,--number=}'[limit to number of commits]'
251 '*:patches:__stg_patches_all'
253 _arguments -s -S $subcmd_args
256 _stg-mail() {
257 __stg_add_args_help
258 __stg_add_args_branch
259 __stg_add_args_diffopts
260 subcmd_args+=(
261 '--to=[add address to To: list]:address'
262 '--cc=[add address to Cc: list]:address'
263 '--bcc=[add address to Bcc: list]:address'
264 '--auto[automatically cc patch signers]'
265 '--no-thread[do not send subsequent messages as replies]'
266 '--unrelated[send patches without sequence numbers]'
267 '(-v --version)'{-v,--version=}'[add version to subject prefix]:version'
268 '--prefix=[add prefix to subject]:prefix'
269 '(-c --cover)'{-c,--cover=}'[cover message file]: :_files'
270 '(-e --edit-cover)'{-e,--edit-cover}'[edit cover message before sending]'
271 '(-E --edit-patches)'{-E,--edit-patches}'[edit patches before sending]'
272 '(-s --sleep)'{-s,--sleep=}'[seconds to sleep between sending emails]:seconds'
273 '--in-reply-to=[reply reference id]:refid'
274 '--domain=[domain to use for message ID]:domain'
275 '(-u --user)'{-u,--user=}'[username for SMTP authentication]:user'
276 '(-p --password)'{-p,--password=}'[password for SMTP authentication]:password'
277 '(-T --smtp-tls)'{-t,--smtp-tls}'[use TLS for SMTP authentication]'
278 + '(send-method)'
279 '--git[use `git send-email`]'
280 '(-m --mbox)'{-m,--mbox}'[generate mbox file instead of sending]'
281 '--smtp-server=[server or command for sending email]'
282 + '(attachment)'
283 '--attach[send patch as attachment]'
284 '--attach-inline[send patch as inline attachment]'
285 '(-t --template)'{-t,--template=}'[message template file]: :_files'
286 + '(patches)'
287 '(-a --all)'{-a,--all}'[email all applied patches]'
288 '*:patches:__stg_patches_all'
290 _arguments -s -S $subcmd_args
293 _stg-new() {
294 __stg_add_args_help
295 __stg_add_args_author
296 __stg_add_args_sign
297 __stg_add_args_hook
298 __stg_add_args_savetemplate
299 subcmd_args+=(
300 '(-v --verbose)'{-v,--verbose}'[show diff of file changes]'
301 ':: :_guard "([^-]?#|)" name'
303 __stg_add_args_message
304 _arguments -s -S $subcmd_args
307 _stg-next() {
308 __stg_add_args_help
309 __stg_add_args_branch
310 _arguments -s -S $subcmd_args
313 _stg-patches() {
314 __stg_add_args_help
315 __stg_add_args_branch
316 __stg_add_args_diffopts
317 subcmd_args+=(
318 '(-d --diff)'{-d,--diff}'[show diffs of given files]'
319 '*:files:__stg_files_known'
321 _arguments -s -S $subcmd_args
324 _stg-pick() {
325 # TODO: complete --parent commit id
326 __stg_add_args_help
327 subcmd_args+=(
328 '(-n --name)'{-n,--name=}'[name for picked patch]:name'
329 '(-B --ref-branch)'{-B,--ref-branch=}'[pick patches from branch]: :__stg_branch_stgit'
330 '(-r --revert)'{-r,--revert}'[revert given commit object]'
331 '(-p --parent=)'{-p,--parent}'[use commit id as parent]:commit'
332 '(-x --expose)'{-x,--expose}'[append imported commit id to patch log]'
333 '--unapplied[keep patch unapplied]'
334 '*'{-f,--file=}'[only fold given file]: :_files'
335 '*:patches:__stg_patches_refbranch'
336 + '(mode)'
337 '--fold[fold the commit into current patch]'
338 '--update[fold limited to current patch files]'
340 _arguments -s -S $subcmd_args
343 _stg-pop() {
344 __stg_add_args_help
345 __stg_add_args_keep
346 subcmd_args+=(
347 '(-s --spill)'{-s,--spill}'[pop a patch keeping its modifications in the tree]'
348 - group-number
349 '(-n --number)'{-n+,--number=}'[push specified number of patches]:number'
350 - group-all
351 '(-a --all)'{-a,--all}'[push all unapplied patches]'
352 - group-patches
353 '*:applied patches:__stg_patches_applied'
355 _arguments -s -S $subcmd_args
358 _stg-prev() {
359 __stg_add_args_help
360 __stg_add_args_branch
361 _arguments -s -S $subcmd_args
364 _stg-pull() {
365 __stg_add_args_help
366 __stg_add_args_merged
367 subcmd_args+=(
368 '(-n --nopush)'{-n,--nopush}'[do not push patches after rebasing]'
369 ':repository:__stg_remotes'
371 _arguments -s -S $subcmd_args
374 _stg-push() {
375 __stg_add_args_help
376 __stg_add_args_keep
377 __stg_add_args_merged
378 subcmd_args+=(
379 '--reverse[push patches in reverse order]'
380 '--noapply[push without applying]'
381 '--set-tree[push patch with the original tree]'
382 - group-all
383 '(-a --all)'{-a,--all}'[push all unapplied patches]'
384 - group-number
385 '(-n --number)'{-n+,--number=}'[push specified number of patches]:number'
386 - group-patches
387 '*:unapplied patches:__stg_patches_unapplied'
389 _arguments -s -S $subcmd_args
392 _stg-rebase() {
393 __stg_add_args_help
394 __stg_add_args_merged
395 subcmd_args+=(
396 '(-n --nopush)'{-n,--nopush}'[do not push patches after rebasing]'
397 ':new-base-id:__stg_heads'
399 _arguments -s -S $subcmd_args
402 _stg-redo() {
403 __stg_add_args_help
404 subcmd_args+=(
405 '--hard[discard changes in index/worktree]'
406 '(-n --number)'{-n+,--number=}'[number of undos to redo]:number'
408 _arguments -s -S $subcmd_args
411 _stg-refresh() {
412 __stg_add_args_help
413 __stg_add_args_author
414 __stg_add_args_edit
415 __stg_add_args_hook
416 __stg_add_args_sign
417 __stg_add_args_diffopts
418 subcmd_args+=(
419 '(-a --annotate)'{-a,--annotate=}'[annotate patch log entry]:note'
420 '(-d --diff)'{-d,--diff}'[show diff when editing patch message]'
421 '(-F --force)'{-F,--force}'[force refresh even if index is dirty]'
422 '(-i --index)'{-i,--index}'[refresh from index instead of worktree]'
423 '(-p --patch)'{-p,--patch=}'[refresh patch other than top patch]: :__stg_patches_all'
424 '--spill[Spill patch contents to worktree and index, and erase patch content]'
425 + '(update-files)'
426 '(-u --update)'{-u,--update}'[only update current patch files]'
427 '*:files:__stg_changed_files'
428 + '(submodules)'
429 '(-s --submodules)'{-s,--submodules}'[include submodules in refresh]'
430 '--no-submodules[exclude submodules from refresh]'
432 __stg_add_args_message
433 _arguments -s -S $subcmd_args
436 _stg-rename() {
437 __stg_add_args_help
438 __stg_add_args_branch
439 subcmd_args+=(
440 ':old-patch:__stg_patches_all'
442 _arguments -s -S $subcmd_args
445 _stg-repair() {
446 __stg_add_args_help
447 _arguments -s $subcmd_args
450 _stg-reset() {
451 __stg_add_args_help
452 subcmd_args+=(
453 '--hard[discard changes in index/worktree]'
454 ':state:'
455 '*:patches:__stg_patches_all'
457 _arguments -s -S $subcmd_args
460 _stg-series() {
461 __stg_add_args_help
462 __stg_add_args_branch
463 subcmd_args+=(
464 '--author[show the author name for each patch]'
465 '(-c --count)'{-c,--count}'[print number of patches]'
466 '(-d --description)'{-d,--description}'[show short descriptions]'
467 '--no-description[do not show patch descriptions]'
468 '(-e --empty)'{-e,--empty}'[identify empty patches]'
469 '(-m --missing)'{-m,--missing=}'[show patches from branch missing in current]: :__stg_branch_stgit'
470 '--noprefix[do not show the patch status prefix]'
471 '(-s --short)'{-s,--short}'[list just patches around the topmost patch]'
472 '--showbranch[show branch name of listed patches]'
473 - group-ahu
474 '(-A --applied)'{-A,--applied}'[show applied patches]'
475 '(-H --hidden)'{-H,--hidden}'[show hidden patches]'
476 '(-U --unapplied)'{-U,--unapplied}'[show unapplied patches]'
477 - group-all
478 '(-a --all)'{-a,--all}'[show all patches including hidden]'
479 - group-patches
480 ':patches:__stg_patches_all'
482 _arguments -s -S $subcmd_args
485 _stg-show() {
486 __stg_add_args_help
487 __stg_add_args_branch
488 __stg_add_args_diffopts
489 subcmd_args+=(
490 '(-s --stat)'{-s,--stat}'[show diff stat]'
491 '*:patches:__stg_patches_all'
492 + '(patch-selection)'
493 '(-a --applied)'{-a,--applied}'[show applied patches]'
494 '(-u --unapplied)'{-u,--unapplied}'[show unapplied patches]'
496 _arguments -s -S $subcmd_args
499 _stg-sink() {
500 __stg_add_args_help
501 __stg_add_args_keep
502 subcmd_args+=(
503 '(-n --nopush)'{-n,--nopush}'[do not push patches after sinking]'
504 '(-t --to)'{-t,--to=}'[sink patches below target patch]: :__stg_patches_applied'
505 '*:patches:__stg_patches_all'
507 _arguments -s -S $subcmd_args
510 _stg-squash() {
511 __stg_add_args_help
512 __stg_add_args_hook
513 __stg_add_args_savetemplate
514 subcmd_args+=(
515 '(-n --name)'{-n,--name=}'[name for squashed patch]: :__stg_patches_all'
516 '*:patches:__stg_patches_all_allow_dups'
518 __stg_add_args_message
519 _arguments -s -S $subcmd_args
522 _stg-sync() {
523 __stg_add_args_help
524 subcmd_args+=(
525 + '(patches)'
526 '(-a --all)'{-a,--all}'[synchronize all applied patches]'
527 '*:patches:__stg_patches_refbranch'
528 + '(source)'
529 '(-B --ref-branch)'{-B,--ref-branch}'[synchronize patches with branch]: :__stg_branch_stgit'
530 '(-s --series)'{-s,--series=}'[synchronize patches with series]: :_files'
532 _arguments -s -S $subcmd_args
535 _stg-top() {
536 __stg_add_args_help
537 __stg_add_args_branch
538 _arguments -s -S $subcmd_args
541 _stg-uncommit() {
542 __stg_add_args_help
543 subcmd_args+=(
544 - group-number
545 '(-n --number)'{-n+,--number=}'[push specified number of patches]:number'
546 ':prefix:'
547 - group-to
548 '(-t --to)'{-t,--to=}'[uncommit to the specified commit]:commit'
549 '(-x --exclusive)'{-x,--exclusive}'[exclude the commit specified by --to]'
550 - group-names
551 '*: :_guard "([^-]?#|)" names'
553 _arguments -s -S $subcmd_args
556 _stg-undo() {
557 __stg_add_args_help
558 subcmd_args+=(
559 '--hard[discard changes in index/worktree]'
560 '(-n --number)'{-n+,--number=}'[number commands to undo]:number'
562 _arguments -s -S $subcmd_args
565 _stg-unhide() {
566 __stg_add_args_help
567 __stg_add_args_branch
568 subcmd_args+=(
569 ':patches:__stg_patches_hidden'
571 _arguments -s -S $subcmd_args
574 __stg_add_args_author() {
575 subcmd_args+=(
576 '--author=[set author details]'
577 '--authdate=[set author date]:date'
578 '--authemail=[set author email]:email'
579 '--authname=[set author name]:name'
583 __stg_add_args_branch() {
584 subcmd_args+=(
585 '(-b --branch)'{-b,--branch=}'[specify another branch]: :__stg_branch_stgit'
589 __stg_add_args_diffopts() {
590 # TODO: complete diff-opts values (with separators?)
591 subcmd_args+=(
592 '(-O --diff-opts)'{-O+,--diff-opts=}'[extra options for git diff]:opts'
596 __stg_add_args_edit() {
597 subcmd_args+=(
598 '(-e --edit)'{-e,--edit}'[invoke interactive editor]'
602 __stg_add_args_help() {
603 subcmd_args+=(
604 '(- *)'{-h,--help}'[show help message and exit]'
608 __stg_add_args_hook() {
609 subcmd_args+=(
610 '--no-verify[disable commit-msg hook]'
614 __stg_add_args_keep() {
615 subcmd_args+=(
616 '(-k --keep)'{-k,--keep}'[keep local changes]'
620 __stg_add_args_merged() {
621 subcmd_args+=(
622 '(-m --merged)'{-m,--merged}'[check for patches merged upstream]'
626 __stg_add_args_message() {
627 subcmd_args+=(
628 + '(message)'
629 '(-f --file)'{-f,--file=}'[use message file instead of invoking editor]: :_files'
630 '(-m --message)'{-m,--message=}'[specify message instead of invoking editor]:message'
634 __stg_add_args_savetemplate() {
635 subcmd_args+=(
636 '--save-template=[save message template to file and exit]: :_files'
640 __stg_add_args_sign() {
641 subcmd_args+=(
642 '--ack[add Acked-by trailer]'
643 '--ack-by[add Acked-by trailer]:value'
644 '--review[add Reviewed-by trailer]'
645 '--review-by[add Reviewed-by trailer]:value'
646 '--sign[add Signed-off-by trailer]'
647 '--sign-by[add Signed-off-by trailer]:value'
651 __stg_heads () {
652 _alternative 'heads-local::__stg_heads_local' 'heads-remote::__stg_heads_remote'
655 __stg_heads_local () {
656 local f gitdir
657 declare -a heads
659 heads=(${(f)"$(_call_program headrefs git for-each-ref --format='"%(refname:short)"' refs/heads 2>/dev/null)"})
660 gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null)
661 if __stg_git_command_successful $pipestatus; then
662 for f in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
663 [[ -f $gitdir/$f ]] && heads+=$f
664 done
665 [[ -f $gitdir/refs/stash ]] && heads+=stash
666 [[ -f $gitdir/refs/bisect/bad ]] && heads+=bisect/bad
669 __stg_git_describe_commit heads heads-local "local head" "$@"
672 __stg_heads_remote () {
673 declare -a heads
675 heads=(${(f)"$(_call_program headrefs git for-each-ref --format='"%(refname:short)"' refs/remotes 2>/dev/null)"})
677 __stg_git_describe_commit heads heads-remote "remote head" "$@"
680 __stg_git_command_successful () {
681 if (( ${#*:#0} > 0 )); then
682 _message 'not a git repository'
683 return 1
685 return 0
688 __stg_git_describe_commit () {
689 __stg_git_describe_branch $1 $2 $3 -M 'r:|/=* r:|=*' "${(@)argv[4,-1]}"
692 __stg_git_describe_branch () {
693 local __commits_in=$1
694 local __tag=$2
695 local __desc=$3
696 shift 3
698 integer maxverbose
699 if zstyle -s :completion:$curcontext: max-verbose maxverbose &&
700 (( ${compstate[nmatches]} <= maxverbose )); then
701 local __c
702 local -a __commits
703 for __c in ${(P)__commits_in}; do
704 __commits+=("${__c}:${$(_call_program describe git rev-list -1 --oneline $__c)//:/\\:}")
705 done
706 _describe -t $__tag $__desc __commits "$@"
707 else
708 local expl
709 _wanted $__tag expl $__desc compadd "$@" -a - $__commits_in
713 __stg_branch_stgit() {
714 declare -a stg_branches
715 stg_branches=(
716 ${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/stacks 2>/dev/null)"}#refs/stacks/}
718 local expl
719 _wanted -V branches expl "branch" compadd $stg_branches
722 __stg_files_relative() {
723 local prefix
724 prefix=$(_call_program gitprefix git rev-parse --show-prefix 2>/dev/null)
725 if (( $#prefix == 0 )); then
726 print $1
727 return
730 local file
731 local -a files
733 files=()
734 # Collapse "//" and "/./" into "/". Strip any remaining "/." and "/".
735 for file in ${${${${${(0)1}//\/\///}//\/.\///}%/.}%/}; do
736 integer i n
737 (( n = $#file > $#prefix ? $#file : $#prefix ))
738 for (( i = 1; i <= n; i++ )); do
739 if [[ $file[i] != $prefix[i] ]]; then
740 while (( i > 0 )) && [[ $file[i-1] != / ]]; do
741 (( i-- ))
742 done
743 break
745 done
747 files+=${(l@${#prefix[i,-1]//[^\/]}*3@@../@)}${file[i,-1]}
748 done
750 print ${(pj:\0:)files}
753 __stg_diff-index_files () {
754 local tree=$1 description=$2 tag=$3; shift 3
755 local files expl
757 # $tree needs to be escaped for _call_program; matters for $tree = "HEAD^"
758 files=$(_call_program files git diff-index -z --name-only --no-color --cached ${(q)tree} 2>/dev/null)
759 __stg_git_command_successful $pipestatus || return 1
760 files=(${(0)"$(__stg_files_relative $files)"})
761 __stg_git_command_successful $pipestatus || return 1
763 _wanted $tag expl $description _multi_parts $@ - / files
766 __stg_changed-in-index_files () {
767 __stg_diff-index_files HEAD 'changed in index file' changed-in-index-files "$@"
770 __stg_changed-in-working-tree_files () {
771 local files expl
773 files=$(_call_program changed-in-working-tree-files git diff -z --name-only --no-color 2>/dev/null)
774 __stg_git_command_successful $pipestatus || return 1
775 files=(${(0)"$(__stg_files_relative $files)"})
776 __stg_git_command_successful $pipestatus || return 1
778 _wanted changed-in-working-tree-files expl 'changed in working tree file' _multi_parts $@ -f - / files
781 __stg_changed_files () {
782 _alternative \
783 'changed-in-index-files::__stg_changed-in-index_files' \
784 'changed-in-working-tree-files::__stg_changed-in-working-tree_files'
787 __stg_files_known() {
788 declare -a known_files
789 known_files=(
790 ${(f)"$(_call_program known-files git ls-files 2>/dev/null)"}
792 local expl
793 _wanted -V known-files expl "known files" _multi_parts - / known_files
796 __stg_get_branch_opt() {
797 local short long i
798 short=${1:-'-b'}
799 long=${2:-'--branch'}
800 i=${words[(I)$short|$long(=*|)]}
801 case ${words[i]} in
802 $short|$long)
803 if (( i < $#words )); then
804 echo "--branch=${words[i + 1]}"
808 echo "--branch=${words[i]#*=}"
810 esac
813 __stg_want_patches() {
814 declare -a patches
815 local expl
816 patches=(
817 ${(f)"$(_call_program want-patches stg series --no-description --noprefix $@ 2>/dev/null)"}
819 _wanted -V all expl "patch" compadd ${patches:|words}
823 __stg_patches_all() {
824 __stg_want_patches $(__stg_get_branch_opt) --all
827 __stg_patches_all_allow_dups() {
828 declare -a patches
829 local expl branch_opt
830 branch_opt=$(__stg_get_branch_opt)
831 patches=(
832 ${(f)"$(_call_program all-patches stg series $branch_opt --no-description --noprefix --all 2>/dev/null)"}
834 _wanted -V all expl "patch" compadd ${patches}
837 __stg_patches_applied() {
838 __stg_want_patches $(__stg_get_branch_opt) --applied
841 __stg_patches_hidden() {
842 __stg_want_patches $(__stg_get_branch_opt) --hidden
845 __stg_patches_unapplied() {
846 __stg_want_patches $(__stg_get_branch_opt) --unapplied
849 __stg_patches_unhidden() {
850 __stg_want_patches $(__stg_get_branch_opt) --applied --unapplied
853 __stg_patches_refbranch() {
854 __stg_want_patches $(__stg_get_branch_opt -B --ref-branch) --all
857 __stg_remotes() {
858 local remotes expl
859 remotes=(${(f)"$(_call_program remotes git remote 2>/dev/null)"})
860 _wanted remotes expl remote compadd "$@" -a - remotes
863 __stg_subcommands() {
864 _describe -t commands 'stgit command' _stg_cmds
867 __stg_caching_policy() {
868 [[ =$service -nt $1 ]]
871 _stgit() {
872 local curcontext="$curcontext" state line expl ret=1
873 typeset -A opt_args
875 # Special cases for git aliases
876 case "$words[2]" in
877 (add|mv|rm|status)
878 words[1]=git
880 (resolved)
881 words[1]=git
882 words[2]=add
884 esac
885 if [ "$words[1]" = git ]; then
886 _normal && ret=0
887 return ret
890 local update_policy
891 zstyle -s ":completion:*:*:stg:*" cache-policy update_policy
892 if [[ -z "$update_policy" ]]; then
893 zstyle ":completion:*:*:stg:*" cache-policy __stg_caching_policy
896 _arguments -C -A "-*" \
897 '(-)--help[print help information]' \
898 '(*)--version[display version information]' \
899 '1: :->command' \
900 '*:: :->args' && ret=0
902 if [[ -n $state ]] && (( ! $+_stg_cmds )); then
903 typeset -a _stg_cmds
904 if _cache_invalid stg-cmds || ! _retrieve_cache stg-cmds; then
905 _stg_cmds=(
906 ${${${(M)${(f)"$(stg help 2> /dev/null)"}## *}# }/#(#b)([^[:space:]]##)[[:space:]]##(*)/$match[1]:$match[2]}
908 if (( $? == 0 )); then
909 _store_cache stg-cmds _stg_cmds
910 else
911 unset _stg_cmds
916 case $state in
917 (command)
918 __stg_subcommands && ret=0
920 (args)
921 local -a subcmd_args
922 local subcmd=$words[1]
923 curcontext="${curcontext%:*:*}:stg-$subcmd:"
924 if ! _call_function ret _stg-$subcmd; then
925 _message "unknown sub-command: $subcmd"
928 esac
930 return ret
933 _stgit "$@"