3 # This script implements zsh completions for StGit (stg).
5 # To use these completions, copy to a directory in $fpath as _stgit.
9 # $ cp completion/stgit.zsh ~/.zsh.d/_stgit
12 # fpath=("$HOME/.zsh.d" $fpath)
13 # autoload -U compinit
20 '--list[list branches]'
22 '--merge[merge worktree changes into other branch]'
23 ':branch:__stg_branch_stgit'
25 '--create[create and switch to new branch]'
29 '--clone[clone current branch to new branch]'
32 '(-r --rename)'{-r,--rename}'[rename existing branch]'
33 ':branch:__stg_branch_stgit'
36 '(-p --protect)'{-p,--protect}'[prevent stg from modifying branch]'
37 ':branch:__stg_branch_stgit'
39 '(-u --unprotect)'{-u,--unprotect}'[allow stg to modify branch]'
40 ':branch:__stg_branch_stgit'
42 '--delete[delete branch]'
43 '--force[force delete when series is non-empty]'
44 ':branch:__stg_branch_stgit'
46 '--cleanup[cleanup stg metadata for branch]'
47 '--force[force cleanup when series is non-empty]'
48 ':branch:__stg_branch_stgit'
50 '(-d --description)'{-d,--description}'[set branch description]:description'
51 ':branch:__stg_branch_stgit'
53 _arguments
-s -S $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
71 _arguments
-s $subcmd_args
78 '(-a --all)'{-a,--all}'[commit all unapplied patches]'
80 '(-n --number)'{-n+,--number=}'[commit specified number of patches]:number'
82 '*:applied patches:__stg_patches_applied'
84 _arguments
-s -S $subcmd_args
91 '--spill[spill patch contents to worktree and index]'
93 '(-t --top)'{-t,--top}'[delete top patch]'
95 '*:patches:__stg_patches_all'
97 _arguments
-s -S $subcmd_args
102 __stg_add_args_diffopts
104 '(-r --range)'{-r,--range=}'[show diff between revisions]: :__stg_patches_all'
105 '(-s --stat)'{-s,--stat}'[show stat instead of diff]'
106 '*:files:__stg_files_dirty'
108 _arguments
-s -S $subcmd_args
113 __stg_add_args_author
114 __stg_add_args_diffopts
117 __stg_add_args_savetemplate
120 '(-d --diff)'{-d,--diff}'[edit patch diff]'
121 '(-t --set-tree)'{-t,--set-tree=}'[set git tree of patch]:treeish'
122 ':patch:__stg_patches_all'
124 __stg_add_args_message
125 _arguments
-s -S $subcmd_args
130 __stg_add_args_branch
131 __stg_add_args_diffopts
133 '(-d --dir)'{-d,--dir}'[export patches to directory]: :_directories'
134 '(-n --numbered)'{-n,--numbered}'[prefix patch names with order numbers]'
135 '(-s --stdout)'{-s,--stdout}'[dump patches to standard output]'
136 '(-t --template)'{-t,--template=}'[use template file]: :_files'
137 '*:patches:__stg_patches_unhidden'
139 '(-e --extension)'{-e,--extension=}'[extension to append to patch names]:extension'
140 '(-p --patch)'{-p,--patch}'[append .patch to patch names]'
142 _arguments
-s -S $subcmd_args
147 __stg_add_args_diffopts
149 '--bare[bare file names]'
150 '(-s --stat)'{-s,--stat}'[show diff stat]'
151 ':patches:__stg_patches_all'
153 _arguments
-s -S $subcmd_args
160 '(-s --series)'{-s,--series=}'[arrange according to series file]: :_files'
161 ':patches:__stg_patches_all'
163 _arguments
-s -S $subcmd_args
169 '(-b --base)'{-b,--base=}'[apply on base commit instead of HEAD]:commit'
170 '(-p --strip)'{-p+,--strip=}'[remove N leading directories from diff paths]:num'
171 '--reject[leave rejected hunks in .rej files]'
174 _arguments
-s -S $subcmd_args
180 __stg_add_args_merged
182 ':patches:__stg_patches_all'
184 _arguments
-s -S $subcmd_args
188 _arguments
-s ':commands:__stg_subcommands'
193 __stg_add_args_branch
195 ':patches:__stg_patches_unhidden'
197 _arguments
-s -S $subcmd_args
203 ':references:__stg_patches_all'
205 _arguments
-s -S $subcmd_args
210 __stg_add_args_author
214 '(-n --name)'{-n,--name}'[name for imported patch]'
215 '(-p --strip)'{-p+,--strip=}'[remove N leading directories from diff paths]:num'
216 '(-t --stripname)'{-t,--stripname}'[strip number and extension from patch name]'
217 '(-i --ignore)'{-i,--ignore}'[ingore applied patches in series]'
218 '--replace[replace unapplied patches in series]'
219 '--reject[leave rejected hunks in .rej files]'
220 '--keep-cr[do not remove CR from email lines ending with CRLF]'
221 '(-d --showdiff)'{-d,--showdiff}'[show patch content in editor buffer]'
224 '(-m --mail)'{-m,--mail}'[import from standard email file]'
225 '(-M --mbox)'{-M,--mbox}'[import from mbox file]'
226 '(-s --series)'{-s,--series}'[import from series file]'
227 '(-u --url)'{-u,--url}'[import patch from URL]'
229 _arguments
-s -S $subcmd_args
234 _arguments
-s $subcmd_args
239 __stg_add_args_branch
241 '--clear[clear log history]'
242 '(-d --diff)'{-d,--diff}'[show refresh diffs]'
243 '(-f --full)'{-f,--full}'[show full commit ids]'
244 '(-g --graphical)'{-g,--graphical}'[show log in gitk]'
245 '(-n --number)'{-n+,--number=}'[limit to number of commits]'
246 '*:patches:__stg_patches_all'
248 _arguments
-s -S $subcmd_args
253 __stg_add_args_branch
254 __stg_add_args_diffopts
256 '--to=[add address to To: list]:address'
257 '--cc=[add address to Cc: list]:address'
258 '--bcc=[add address to Bcc: list]:address'
259 '--auto[automatically cc patch signers]'
260 '--no-thread[do not send subsequent messages as replies]'
261 '--unrelated[send patches without sequence numbers]'
262 '(-v --version)'{-v,--version=}'[add version to subject prefix]:version'
263 '--prefix=[add prefix to subject]:prefix'
264 '(-c --cover)'{-c,--cover=}'[cover message file]: :_files'
265 '(-e --edit-cover)'{-e,--edit-cover}'[edit cover message before sending]'
266 '(-E --edit-patches)'{-E,--edit-patches}'[edit patches before sending]'
267 '(-s --sleep)'{-s,--sleep=}'[seconds to sleep between sending emails]:seconds'
268 '--in-reply-to=[reply reference id]:refid'
269 '--domain=[domain to use for message ID]:domain'
270 '(-u --user)'{-u,--user=}'[username for SMTP authentication]:user'
271 '(-p --password)'{-p,--password=}'[password for SMTP authentication]:password'
272 '(-T --smtp-tls)'{-t,--smtp-tls}'[use TLS for SMTP authentication]'
274 '--git[use `git send-email`]'
275 '(-m --mbox)'{-m,--mbox}'[generate mbox file instead of sending]'
276 '--smtp-server=[server or command for sending email]'
278 '--attach[send patch as attachment]'
279 '--attach-inline[send patch as inline attachment]'
280 '(-t --template)'{-t,--template=}'[message template file]: :_files'
282 '(-a --all)'{-a,--all}'[email all applied patches]'
283 '*:patches:__stg_patches_all'
285 _arguments
-s -S $subcmd_args
290 __stg_add_args_author
293 __stg_add_args_savetemplate
297 __stg_add_args_message
298 _arguments
-s -S $subcmd_args
303 __stg_add_args_branch
304 _arguments
-s -S $subcmd_args
309 __stg_add_args_branch
310 __stg_add_args_diffopts
312 '(-d --diff)'{-d,--diff}'[show diffs of given files]'
313 '*:files:__stg_files_known'
315 _arguments
-s -S $subcmd_args
319 # TODO: consider --ref-branch for patches completion
320 # TODO: complete --parent commit id
323 '(-n --name)'{-n,--name=}'[name for picked patch]:name'
324 '(-B --ref-branch)'{-B,--ref-branch=}'[pick patches from branch]: :__stg_branch_stgit'
325 '(-r --revert)'{-r,--revert}'[revert given commit object]'
326 '(-p --parent=)'{-p,--parent}'[use commit id as parent]:commit'
327 '(-x --expose)'{-x,--expose}'[append imported commit id to patch log]'
328 '--unapplied[keep patch unapplied]'
329 '*'{-f,--file=}'[only fold given file]: :_files'
330 '*:patches:__stg_patches_all'
332 '--fold[fold the commit into current patch]'
333 '--update[fold limited to current patch files]'
335 _arguments
-s -S $subcmd_args
342 '(-s --spill)'{-s,--spill}'[pop a patch keeping its modifications in the tree]'
344 '(-n --number)'{-n+,--number=}'[push specified number of patches]:number'
346 '(-a --all)'{-a,--all}'[push all unapplied patches]'
348 '*:applied patches:__stg_patches_applied'
350 _arguments
-s -S $subcmd_args
355 __stg_add_args_branch
356 _arguments
-s -S $subcmd_args
361 __stg_add_args_merged
363 '(-n --nopush)'{-n,--nopush}'[do not push patches after rebasing]'
364 ':repository:__stg_remotes'
366 _arguments
-s -S $subcmd_args
372 __stg_add_args_merged
374 '--reverse[push patches in reverse order]'
375 '--set-tree[push patch with the original tree]'
377 '(-a --all)'{-a,--all}'[push all unapplied patches]'
379 '(-n --number)'{-n+,--number=}'[push specified number of patches]:number'
381 '*:unapplied patches:__stg_patches_unapplied'
383 _arguments
-s -S $subcmd_args
388 __stg_add_args_merged
390 '(-n --nopush)'{-n,--nopush}'[do not push patches after rebasing]'
393 _arguments
-s -S $subcmd_args
399 '--hard[discard changes in index/worktree]'
400 '(-n --number)'{-n+,--number=}'[number of undos to redo]:number'
402 _arguments
-s -S $subcmd_args
407 __stg_add_args_author
412 '(-a --annotate)'{-a,--annotate=}'[annotate patch log entry]:note'
413 '(-F --force)'{-F,--force}'[force refresh even if index is dirty]'
414 '(-i --index)'{-i,--index}'[refresh from index instead of worktree]'
415 '(-p --patch)'{-p,--patch=}'[refresh patch other than top patch]: :__stg_patches_applied'
416 '--spill[Spill patch contents to worktree and index, and erase patch content]'
418 '(-u --update)'{-u,--update}'[only update current patch files]'
419 '*:files:__stg_files_dirty'
421 '(-s --submodules)'{-s,--submodules}'[include submodules in refresh]'
422 '--no-submodules[exclude submodules from refresh]'
424 __stg_add_args_message
425 _arguments
-s -S $subcmd_args
430 __stg_add_args_branch
432 ':old-patch:__stg_patches_all'
434 _arguments
-s -S $subcmd_args
439 _arguments
-s $subcmd_args
445 '--hard[discard changes in index/worktree]'
447 '*:patches:__stg_patches_all'
449 _arguments
-s -S $subcmd_args
454 __stg_add_args_branch
456 '--author[show the author name for each patch]'
457 '(-c --count)'{-c,--count}'[print number of patches]'
458 '(-d --description)'{-d,--description}'[show short descriptions]'
459 '--no-description[do not show patch descriptions]'
460 '(-e --empty)'{-e,--empty}'[identify empty patches]'
461 '(-m --missing)'{-m,--missing=}'[show patches from branch missing in current]: :__stg_branch_stgit'
462 '--noprefix[do not show the patch status prefix]'
463 '(-s --short)'{-s,--short}'[list just patches around the topmost patch]'
464 '--showbranch[show branch name of listed patches]'
466 '(-A --applied)'{-A,--applied}'[show applied patches]'
467 '(-H --hidden)'{-H,--hidden}'[show hidden patches]'
468 '(-U --unapplied)'{-U,--unapplied}'[show unapplied patches]'
470 '(-a --all)'{-a,--all}'[show all patches including hidden]'
472 ':patches:__stg_patches_all'
474 _arguments
-s -S $subcmd_args
479 __stg_add_args_branch
480 __stg_add_args_diffopts
482 '(-s --stat)'{-s,--stat}'[show diff stat]'
483 '*:patches:__stg_patches_all'
484 + '(patch-selection)'
485 '(-a --applied)'{-a,--applied}'[show applied patches]'
486 '(-u --unapplied)'{-u,--unapplied}'[show unapplied patches]'
488 _arguments
-s -S $subcmd_args
495 '(-n --nopush)'{-n,--nopush}'[do not push patches after sinking]'
496 '(-t --to)'{-t,--to=}'[sink patches below target patch]: :__stg_patches_applied'
497 ':patches:__stg_patches_all'
499 _arguments
-s -S $subcmd_args
505 __stg_add_args_savetemplate
507 '(-n --name)'{-n,--name=}'[name for squashed patch]: :__stg_patches_all'
508 '*:patches:__stg_patches_all_allow_dups'
510 __stg_add_args_message
511 _arguments
-s -S $subcmd_args
515 # TODO: complete patches based on --ref-branch
519 '(-a --all)'{-a,--all}'[synchronize all applied patches]'
520 '*:patches:__stg_patches_all'
522 '(-B --ref-branch)'{-B,--ref-branch}'[synchronize patches with branch]: :__stg_branch_stgit'
523 '(-s --series)'{-s,--series=}'[synchronize patches with series]: :_files'
525 _arguments
-s -S $subcmd_args
530 __stg_add_args_branch
531 _arguments
-s -S $subcmd_args
538 '(-n --number)'{-n+,--number=}'[push specified number of patches]:number'
541 '(-t --to)'{-t,--to=}'[uncommit to the specified commit]:commit'
542 '(-x --exclusive)'{-x,--exclusive}'[exclude the commit specified by --to]'
546 _arguments
-s -S $subcmd_args
552 '--hard[discard changes in index/worktree]'
553 '(-n --number)'{-n+,--number=}'[number commands to undo]:number'
555 _arguments
-s -S $subcmd_args
560 __stg_add_args_branch
562 ':patches:__stg_patches_hidden'
564 _arguments
-s -S $subcmd_args
567 __stg_add_args_author
() {
569 '--author=[set author details]'
570 '--authdate=[set author date]:date'
571 '--authemail=[set author email]:email'
572 '--authname=[set author name]:name'
576 __stg_add_args_branch
() {
578 '(-b --branch)'{-b,--branch=}'[specify another branch]: :__stg_branch_stgit'
582 __stg_add_args_diffopts
() {
583 # TODO: complete diff-opts values (with separators?)
585 '(-O --diff-opts)'{-O+,--diff-opts=}'[extra options for git diff]:opts'
589 __stg_add_args_edit
() {
591 '(-e --edit)'{-e,--edit}'[invoke interactive editor]'
595 __stg_add_args_help
() {
597 '(- *)'{-h,--help}'[show help message and exit]'
601 __stg_add_args_hook
() {
603 '--no-verify[disable commit-msg hook]'
607 __stg_add_args_keep
() {
609 '(-k --keep)'{-k,--keep}'[keep local changes]'
613 __stg_add_args_merged
() {
615 '(-m --merged)'{-m,--merged}'[check for patches merged upstream]'
619 __stg_add_args_message
() {
622 '(-f --file)'{-f,--file=}'[use message file instead of invoking editor]: :_files'
623 '(-m --message)'{-m,--message=}'[specify message instead of invoking editor]:message'
627 __stg_add_args_savetemplate
() {
629 '--save-template=[save message template to file and exit]: :_files'
633 __stg_add_args_sign
() {
635 '--ack[add Acked-by line]'
636 '--review[add Reviewed-by line]'
637 '--sign[add Signed-off-by line]'
642 declare -a all_branches
644 ${${(f)"$(_call_program remote-branch-refs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}
647 _wanted
-V branches expl
"branch" compadd
$all_branches
650 __stg_branch_stgit
() {
651 declare -a stg_branches
653 ${(u)${${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}:/*.stgit
/}}
656 _wanted
-V branches expl
"branch" compadd
$stg_branches
659 __stg_files_relative
() {
661 prefix
=$
(_call_program gitprefix git rev-parse
--show-prefix 2>/dev
/null
)
662 if (( $#prefix == 0 )); then
671 # Collapse "//" and "/./" into "/". Strip any remaining "/." and "/".
672 for file in ${${${${${(0)1}//\/\///}//\
/.\
///}%/.
}%/}; do
674 (( n
= $#file > $#prefix ?
$#file : $#prefix ))
675 for (( i
= 1; i
<= n
; i
++ )); do
676 if [[ $file[i
] != $prefix[i
] ]]; then
677 while (( i
> 0 )) && [[ $file[i-1
] != / ]]; do
684 files
+=${(l@${#prefix[i,-1]//[^\/]}*3@@../@)}${file[i,-1]}
687 print
${(pj:\0:)files}
690 __stg_files_dirty
() {
691 declare -a dirty_files
693 ${(f)"$(_call_program dirty-files git diff-index --name-only HEAD 2>/dev/null)"}
695 dirty_files
=(${(0)"$(__stg_files_relative $dirty_files)"})
697 _wanted
-V dirty-files expl
"dirty files" _multi_parts
- / dirty_files
700 __stg_files_known
() {
701 declare -a known_files
703 ${(f)"$(_call_program known-files git ls-files 2>/dev/null)"}
706 _wanted
-V known-files expl
"known files" _multi_parts
- / known_files
709 __stg_patches_all
() {
713 ${(f)"$(_call_program all-patches stg series --noprefix --all 2>/dev/null)"}
715 _wanted
-V all expl
"patch" compadd
${patches:|words}
718 __stg_patches_all_allow_dups
() {
722 ${(f)"$(_call_program all-patches stg series --noprefix --all 2>/dev/null)"}
724 _wanted
-V all expl
"patch" compadd
${patches}
727 __stg_patches_applied
() {
731 ${(f)"$(_call_program applied-patches stg series --noprefix --applied 2>/dev/null)"}
733 _wanted
-V applied expl
"patch" compadd
${patches:|words}
736 __stg_patches_hidden
() {
740 ${(f)"$(_call_program unhidden-patches stg series --noprefix --hidden 2>/dev/null)"}
742 _wanted
-V unapplied expl
"patch" compadd
${patches:|words}
745 __stg_patches_unapplied
() {
749 ${(f)"$(_call_program unapplied-patches stg series --noprefix --unapplied 2>/dev/null)"}
751 _wanted
-V unapplied expl
"patch" compadd
${patches:|words}
754 __stg_patches_unhidden
() {
758 ${(f)"$(_call_program unhidden-patches stg series --noprefix --applied --unapplied 2>/dev/null)"}
760 _wanted
-V unapplied expl
"patch" compadd
${patches:|words}
765 remotes
=(${(f)"$(_call_program remotes git remote 2>/dev/null)"})
766 _wanted remotes expl remote compadd
"$@" -a - remotes
769 __stg_subcommands
() {
770 _describe
-t commands
'stgit command' _stg_cmds
773 __stg_caching_policy
() {
774 [[ =$service -nt $1 ]]
778 local curcontext
="$curcontext" state line expl ret
=1
781 # Special cases for git aliases
791 if [ "$words[1]" = git
]; then
797 zstyle
-s ":completion:*:*:stg:*" cache-policy update_policy
798 if [[ -z "$update_policy" ]]; then
799 zstyle
":completion:*:*:stg:*" cache-policy __stg_caching_policy
802 _arguments
-C -A "-*" \
803 '(-)--help[print help information]' \
804 '(*)--version[display version information]' \
806 '*:: :->args' && ret
=0
808 if [[ -n $state ]] && (( ! $
+_stg_cmds
)); then
810 if _cache_invalid stg-cmds ||
! _retrieve_cache stg-cmds
; then
812 ${${${(M)${(f)"$(stg help 2> /dev/null)"}## *}# }/#(#b)([^[:space:]]##)[[:space:]]##(*)/$match[1]:$match[2]}
814 if (( $?
== 0 )); then
815 _store_cache stg-cmds _stg_cmds
824 __stg_subcommands
&& ret
=0
828 local subcmd
=$words[1]
829 curcontext
="${curcontext%:*:*}:stg-$subcmd:"
830 if ! _call_function ret _stg-
$subcmd; then
831 _message
"unknown sub-command: $subcmd"