|
@@ -0,0 +1,163 @@
|
|
|
|
+#compdef hub
|
|
|
|
+
|
|
|
|
+# Zsh will source this file when attempting to autoload the "_hub" function,
|
|
|
|
+# typically on the first attempt to complete the hub command. We define two new
|
|
|
|
+# setup helper routines (one for the zsh-distributed version, one for the
|
|
|
|
+# git-distributed, bash-based version). Then we redefine the "_hub" function to
|
|
|
|
+# call "_git" after some other interception.
|
|
|
|
+#
|
|
|
|
+# This is pretty fragile, if you think about it. Any number of implementation
|
|
|
|
+# changes in the "_git" scripts could cause problems down the road. It would be
|
|
|
|
+# better if the stock git completions were just a bit more permissive about how
|
|
|
|
+# it allowed third-party commands to be added.
|
|
|
|
+
|
|
|
|
+(( $+functions[__hub_setup_zsh_fns] )) ||
|
|
|
|
+__hub_setup_zsh_fns () {
|
|
|
|
+ (( $+functions[_git-alias] )) ||
|
|
|
|
+ _git-alias () {
|
|
|
|
+ _arguments \
|
|
|
|
+ '-s[output shell script suitable for eval]' \
|
|
|
|
+ '1::shell:(zsh bash csh)'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ (( $+functions[_git-browse] )) ||
|
|
|
|
+ _git-browse () {
|
|
|
|
+ _arguments \
|
|
|
|
+ '-u[output the URL]' \
|
|
|
|
+ '2::subpage:(wiki commits issues)'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ (( $+functions[_git-compare] )) ||
|
|
|
|
+ _git-compare () {
|
|
|
|
+ _arguments \
|
|
|
|
+ '-u[output the URL]' \
|
|
|
|
+ ':[start...]end range:'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ (( $+functions[_git-create] )) ||
|
|
|
|
+ _git-create () {
|
|
|
|
+ _arguments \
|
|
|
|
+ '::name (REPOSITORY or ORGANIZATION/REPOSITORY):' \
|
|
|
|
+ '-p[make repository private]' \
|
|
|
|
+ '-d[description]:description' \
|
|
|
|
+ '-h[home page]:repository home page URL:_urls'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ (( $+functions[_git-fork] )) ||
|
|
|
|
+ _git-fork () {
|
|
|
|
+ _arguments \
|
|
|
|
+ '--no-remote[do not add a remote for the new fork]'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ (( $+functions[_git-pull-request] )) ||
|
|
|
|
+ _git-pull-request () {
|
|
|
|
+ _arguments \
|
|
|
|
+ '-f[force (skip check for local commits)]' \
|
|
|
|
+ '-b[base]:base ("branch", "owner\:branch", "owner/repo\:branch"):' \
|
|
|
|
+ '-h[head]:head ("branch", "owner\:branch", "owner/repo\:branch"):' \
|
|
|
|
+ - set1 \
|
|
|
|
+ '-m[message]' \
|
|
|
|
+ '-F[file]' \
|
|
|
|
+ '-a[user]' \
|
|
|
|
+ '-M[milestone]' \
|
|
|
|
+ '-l[labels]' \
|
|
|
|
+ - set2 \
|
|
|
|
+ '-i[issue]:issue number:' \
|
|
|
|
+ - set3 \
|
|
|
|
+ '::issue-url:_urls'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # stash the "real" command for later
|
|
|
|
+ functions[_hub_orig_git_commands]=$functions[_git_commands]
|
|
|
|
+
|
|
|
|
+ # Replace it with our own wrapper.
|
|
|
|
+ declare -f _git_commands >& /dev/null && unfunction _git_commands
|
|
|
|
+ _git_commands () {
|
|
|
|
+ local ret=1
|
|
|
|
+ # call the original routine
|
|
|
|
+ _call_function ret _hub_orig_git_commands
|
|
|
|
+
|
|
|
|
+ # Effectively "append" our hub commands to the behavior of the original
|
|
|
|
+ # _git_commands function. Using this wrapper function approach ensures
|
|
|
|
+ # that we only offer the user the hub subcommands when the user is
|
|
|
|
+ # actually trying to complete subcommands.
|
|
|
|
+ hub_commands=(
|
|
|
|
+ alias:'show shell instructions for wrapping git'
|
|
|
|
+ pull-request:'open a pull request on GitHub'
|
|
|
|
+ fork:'fork origin repo on GitHub'
|
|
|
|
+ create:'create new repo on GitHub for the current project'
|
|
|
|
+ browse:'browse the project on GitHub'
|
|
|
|
+ compare:'open GitHub compare view'
|
|
|
|
+ ci-status:'lookup commit in GitHub Status API'
|
|
|
|
+ )
|
|
|
|
+ _describe -t hub-commands 'hub command' hub_commands && ret=0
|
|
|
|
+
|
|
|
|
+ return ret
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+(( $+functions[__hub_setup_bash_fns] )) ||
|
|
|
|
+__hub_setup_bash_fns () {
|
|
|
|
+ # TODO more bash-style fns needed here to complete subcommand args. They take
|
|
|
|
+ # the form "_git_CMD" where "CMD" is something like "pull-request".
|
|
|
|
+
|
|
|
|
+ # Duplicate and rename the 'list_all_commands' function
|
|
|
|
+ eval "$(declare -f __git_list_all_commands | \
|
|
|
|
+ sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')"
|
|
|
|
+
|
|
|
|
+ # Wrap the 'list_all_commands' function with extra hub commands
|
|
|
|
+ __git_list_all_commands() {
|
|
|
|
+ cat <<-EOF
|
|
|
|
+alias
|
|
|
|
+pull-request
|
|
|
|
+fork
|
|
|
|
+create
|
|
|
|
+browse
|
|
|
|
+compare
|
|
|
|
+ci-status
|
|
|
|
+EOF
|
|
|
|
+ __git_list_all_commands_without_hub
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # Ensure cached commands are cleared
|
|
|
|
+ __git_all_commands=""
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# redefine _hub to a much smaller function in the steady state
|
|
|
|
+_hub () {
|
|
|
|
+ # only attempt to intercept the normal "_git" helper functions once
|
|
|
|
+ (( $+__hub_func_replacement_done )) ||
|
|
|
|
+ () {
|
|
|
|
+ # At this stage in the shell's execution the "_git" function has not yet
|
|
|
|
+ # been autoloaded, so the "_git_commands" or "__git_list_all_commands"
|
|
|
|
+ # functions will not be defined. Call it now (with a bogus no-op service
|
|
|
|
+ # to prevent premature completion) so that we can wrap them.
|
|
|
|
+ if declare -f _git >& /dev/null ; then
|
|
|
|
+ _hub_noop () { __hub_zsh_provided=1 } # zsh-provided will call this one
|
|
|
|
+ __hub_noop_main () { __hub_git_provided=1 } # git-provided will call this one
|
|
|
|
+ local service=hub_noop
|
|
|
|
+ _git
|
|
|
|
+ unfunction _hub_noop
|
|
|
|
+ unfunction __hub_noop_main
|
|
|
|
+ service=git
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ if (( $__hub_zsh_provided )) ; then
|
|
|
|
+ __hub_setup_zsh_fns
|
|
|
|
+ elif (( $__hub_git_provided )) ; then
|
|
|
|
+ __hub_setup_bash_fns
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ __hub_func_replacement_done=1
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # Now perform the actual completion, allowing the "_git" function to call our
|
|
|
|
+ # replacement "_git_commands" function as needed. Both versions expect
|
|
|
|
+ # service=git or they will call nonexistent routines or end up in an infinite
|
|
|
|
+ # loop.
|
|
|
|
+ service=git
|
|
|
|
+ declare -f _git >& /dev/null && _git
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# make sure we actually attempt to complete on the first "tab" from the user
|
|
|
|
+_hub
|