github.com/jingweno/gh@v2.1.1-0.20221007190738-04a7985fa9a1+incompatible/etc/gh.zsh_completion (about) 1 #compdef hub 2 3 # Zsh will source this file when attempting to autoload the "_hub" function, 4 # typically on the first attempt to complete the hub command. We define two new 5 # setup helper routines (one for the zsh-distributed version, one for the 6 # git-distributed, bash-based version). Then we redefine the "_hub" function to 7 # call "_git" after some other interception. 8 # 9 # This is pretty fragile, if you think about it. Any number of implementation 10 # changes in the "_git" scripts could cause problems down the road. It would be 11 # better if the stock git completions were just a bit more permissive about how 12 # it allowed third-party commands to be added. 13 14 (( $+functions[__hub_setup_zsh_fns] )) || 15 __hub_setup_zsh_fns () { 16 (( $+functions[_git-alias] )) || 17 _git-alias () { 18 _arguments \ 19 '-s[output shell script suitable for eval]' \ 20 '1::shell:(zsh bash csh)' 21 } 22 23 (( $+functions[_git-browse] )) || 24 _git-browse () { 25 _arguments \ 26 '-u[output the URL]' \ 27 '2::subpage:(wiki commits issues)' 28 } 29 30 (( $+functions[_git-compare] )) || 31 _git-compare () { 32 _arguments \ 33 '-u[output the URL]' \ 34 ':[start...]end range:' 35 } 36 37 (( $+functions[_git-create] )) || 38 _git-create () { 39 _arguments \ 40 '::name (REPOSITORY or ORGANIZATION/REPOSITORY):' \ 41 '-p[make repository private]' \ 42 '-d[description]:description' \ 43 '-h[home page]:repository home page URL:_urls' 44 } 45 46 (( $+functions[_git-fork] )) || 47 _git-fork () { 48 _arguments \ 49 '--no-remote[do not add a remote for the new fork]' 50 } 51 52 (( $+functions[_git-pull-request] )) || 53 _git-pull-request () { 54 _arguments \ 55 '-f[force (skip check for local commits)]' \ 56 '-b[base]:base ("branch", "owner\:branch", "owner/repo\:branch"):' \ 57 '-h[head]:head ("branch", "owner\:branch", "owner/repo\:branch"):' \ 58 - set1 \ 59 '-m[message]' \ 60 '-F[file]' \ 61 - set2 \ 62 '-i[issue]:issue number:' \ 63 - set3 \ 64 '::issue-url:_urls' 65 } 66 67 # stash the "real" command for later 68 functions[_hub_orig_git_commands]=$functions[_git_commands] 69 70 # Replace it with our own wrapper. 71 declare -f _git_commands >& /dev/null && unfunction _git_commands 72 _git_commands () { 73 local ret=1 74 # call the original routine 75 _call_function ret _hub_orig_git_commands 76 77 # Effectively "append" our hub commands to the behavior of the original 78 # _git_commands function. Using this wrapper function approach ensures 79 # that we only offer the user the hub subcommands when the user is 80 # actually trying to complete subcommands. 81 hub_commands=( 82 alias:'show shell instructions for wrapping git' 83 pull-request:'open a pull request on GitHub' 84 fork:'fork origin repo on GitHub' 85 create:'create new repo on GitHub for the current project' 86 browse:'browse the project on GitHub' 87 compare:'open GitHub compare view' 88 ci-status:'lookup commit in GitHub Status API' 89 ) 90 _describe -t hub-commands 'gh command' hub_commands && ret=0 91 92 return ret 93 } 94 } 95 96 (( $+functions[__hub_setup_bash_fns] )) || 97 __hub_setup_bash_fns () { 98 # TODO more bash-style fns needed here to complete subcommand args. They take 99 # the form "_git_CMD" where "CMD" is something like "pull-request". 100 101 # Duplicate and rename the 'list_all_commands' function 102 eval "$(declare -f __git_list_all_commands | \ 103 sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')" 104 105 # Wrap the 'list_all_commands' function with extra hub commands 106 __git_list_all_commands() { 107 cat <<-EOF 108 alias 109 pull-request 110 fork 111 create 112 browse 113 compare 114 ci-status 115 release 116 issue 117 update 118 EOF 119 __git_list_all_commands_without_hub 120 } 121 122 # Ensure cached commands are cleared 123 __git_all_commands="" 124 } 125 126 # redefine _hub to a much smaller function in the steady state 127 _hub () { 128 # only attempt to intercept the normal "_git" helper functions once 129 (( $+__hub_func_replacement_done )) || 130 () { 131 # At this stage in the shell's execution the "_git" function has not yet 132 # been autoloaded, so the "_git_commands" or "__git_list_all_commands" 133 # functions will not be defined. Call it now (with a bogus no-op service 134 # to prevent premature completion) so that we can wrap them. 135 if declare -f _git >& /dev/null ; then 136 _hub_noop () { __hub_zsh_provided=1 } # zsh-provided will call this one 137 __hub_noop_main () { __hub_git_provided=1 } # git-provided will call this one 138 local service=hub_noop 139 _git 140 unfunction _hub_noop 141 unfunction __hub_noop_main 142 service=git 143 fi 144 145 if (( $__hub_zsh_provided )) ; then 146 __hub_setup_zsh_fns 147 elif (( $__hub_git_provided )) ; then 148 __hub_setup_bash_fns 149 fi 150 151 __hub_func_replacement_done=1 152 } 153 154 # Now perform the actual completion, allowing the "_git" function to call our 155 # replacement "_git_commands" function as needed. Both versions expect 156 # service=git or they will call nonexistent routines or end up in an infinite 157 # loop. 158 service=git 159 declare -f _git >& /dev/null && _git 160 } 161 162 # make sure we actually attempt to complete on the first "tab" from the user 163 _hub