-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
hub.zsh_completion
174 lines (154 loc) · 5.47 KB
/
hub.zsh_completion
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#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]' \
'--no-edit[use first commit message for pull request title/description]' \
'-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'
pr:'list or checkout a GitHub pull request'
issue:'list or create a GitHub issue'
release:'list or create a GitHub release'
fork:'fork origin repo on GitHub'
create:'create new repo on GitHub for the current project'
delete:'delete a GitHub repo'
browse:'browse the project on GitHub'
compare:'open GitHub compare view'
ci-status:'show status of GitHub checks for a commit'
sync:'update local branches from upstream'
)
_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
pr
issue
release
fork
create
delete
browse
compare
ci-status
sync
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