##// END OF EJS Templates
bash_completion: qfold, qrename, qheader, qclone and qselect
Alexis S. L. Carvalho -
r3484:a8823e68 default
parent child Browse files
Show More
@@ -1,400 +1,435
1 1 # bash completion for the Mercurial distributed SCM
2 2
3 3 # Docs:
4 4 #
5 5 # If you source this file from your .bashrc, bash should be able to
6 6 # complete a command line that uses hg with all the available commands
7 7 # and options and sometimes even arguments.
8 8 #
9 9 # Mercurial allows you to define additional commands through extensions.
10 10 # Bash should be able to automatically figure out the name of these new
11 11 # commands and their options. If you also want to tell it how to
12 12 # complete non-option arguments, see below for how to define an
13 13 # _hg_cmd_foo function.
14 14 #
15 15 #
16 16 # Notes about completion for specific commands:
17 17 #
18 18 # - the completion function for the email command from the patchbomb
19 19 # extension will try to call _hg_emails to get a list of e-mail
20 20 # addresses. It's up to the user to define this function. For
21 21 # example, put the addresses of the lists that you usually patchbomb
22 22 # in ~/.patchbomb-to and the addresses that you usually use to send
23 23 # the patchbombs in ~/.patchbomb-from and use something like this:
24 24 #
25 25 # _hg_emails()
26 26 # {
27 27 # if [ -r ~/.patchbomb-$1 ]; then
28 28 # cat ~/.patchbomb-$1
29 29 # fi
30 30 # }
31 31 #
32 32 #
33 33 # Writing completion functions for additional commands:
34 34 #
35 35 # If it exists, the function _hg_cmd_foo will be called without
36 36 # arguments to generate the completion candidates for the hg command
37 37 # "foo".
38 38 #
39 39 # In addition to the regular completion variables provided by bash,
40 40 # the following variables are also set:
41 41 # - $hg - the hg program being used (e.g. /usr/bin/hg)
42 42 # - $cmd - the name of the hg command being completed
43 43 # - $cmd_index - the index of $cmd in $COMP_WORDS
44 44 # - $cur - the current argument being completed
45 45 # - $prev - the argument before $cur
46 46 # - $global_args - "|"-separated list of global options that accept
47 47 # an argument (e.g. '--cwd|-R|--repository')
48 48 # - $canonical - 1 if we canonicalized $cmd before calling the function
49 49 # 0 otherwise
50 50 #
51 51
52 52 shopt -s extglob
53 53
54 54 _hg_commands()
55 55 {
56 56 local commands
57 57 commands="$("$hg" debugcomplete "$cur" 2>/dev/null)" || commands=""
58 58 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur"))
59 59 }
60 60
61 61 _hg_paths()
62 62 {
63 63 local paths="$("$hg" paths 2>/dev/null | sed -e 's/ = .*$//')"
64 64 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur"))
65 65 }
66 66
67 67 _hg_repos()
68 68 {
69 69 local i
70 70 for i in $(compgen -d -- "$cur"); do
71 71 test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
72 72 done
73 73 }
74 74
75 75 _hg_status()
76 76 {
77 77 local files="$("$hg" status -n$1 . 2>/dev/null)"
78 78 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
79 79 }
80 80
81 81 _hg_tags()
82 82 {
83 83 local tags="$("$hg" tags -q 2>/dev/null)"
84 84 local IFS=$'\n'
85 85 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$tags' -- "$cur"))
86 86 }
87 87
88 88 # this is "kind of" ugly...
89 89 _hg_count_non_option()
90 90 {
91 91 local i count=0
92 92 local filters="$1"
93 93
94 94 for ((i=1; $i<=$COMP_CWORD; i++)); do
95 95 if [[ "${COMP_WORDS[i]}" != -* ]]; then
96 96 if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
97 97 continue
98 98 fi
99 99 count=$(($count + 1))
100 100 fi
101 101 done
102 102
103 103 echo $(($count - 1))
104 104 }
105 105
106 106 _hg()
107 107 {
108 108 local cur prev cmd cmd_index opts i
109 109 # global options that receive an argument
110 110 local global_args='--cwd|-R|--repository'
111 111 local hg="$1"
112 112
113 113 COMPREPLY=()
114 114 cur="$2"
115 115 prev="$3"
116 116
117 117 # searching for the command
118 118 # (first non-option argument that doesn't follow a global option that
119 119 # receives an argument)
120 120 for ((i=1; $i<=$COMP_CWORD; i++)); do
121 121 if [[ ${COMP_WORDS[i]} != -* ]]; then
122 122 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
123 123 cmd="${COMP_WORDS[i]}"
124 124 cmd_index=$i
125 125 break
126 126 fi
127 127 fi
128 128 done
129 129
130 130 if [[ "$cur" == -* ]]; then
131 131 opts=$("$hg" debugcomplete --options "$cmd" 2>/dev/null)
132 132
133 133 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
134 134 return
135 135 fi
136 136
137 137 # global options
138 138 case "$prev" in
139 139 -R|--repository)
140 140 _hg_repos
141 141 return
142 142 ;;
143 143 --cwd)
144 144 # Stick with default bash completion
145 145 return
146 146 ;;
147 147 esac
148 148
149 149 if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
150 150 _hg_commands
151 151 return
152 152 fi
153 153
154 154 # try to generate completion candidates for whatever command the user typed
155 155 local help
156 156 local canonical=0
157 157 if _hg_command_specific; then
158 158 return
159 159 fi
160 160
161 161 # canonicalize the command name and try again
162 162 help=$("$hg" help "$cmd" 2>/dev/null)
163 163 if [ $? -ne 0 ]; then
164 164 # Probably either the command doesn't exist or it's ambiguous
165 165 return
166 166 fi
167 167 cmd=${help#hg }
168 168 cmd=${cmd%%[$' \n']*}
169 169 canonical=1
170 170 _hg_command_specific
171 171 }
172 172
173 173 _hg_command_specific()
174 174 {
175 175 if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
176 176 "_hg_cmd_$cmd"
177 177 return 0
178 178 fi
179 179
180 180 if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
181 181 if [ $canonical = 1 ]; then
182 182 _hg_tags
183 183 return 0
184 184 elif [[ status != "$cmd"* ]]; then
185 185 _hg_tags
186 186 return 0
187 187 else
188 188 return 1
189 189 fi
190 190 fi
191 191
192 192 case "$cmd" in
193 193 help)
194 194 _hg_commands
195 195 ;;
196 196 export)
197 197 if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then
198 198 return 0
199 199 fi
200 200 _hg_tags
201 201 ;;
202 202 manifest|update)
203 203 _hg_tags
204 204 ;;
205 205 pull|push|outgoing|incoming)
206 206 _hg_paths
207 207 _hg_repos
208 208 ;;
209 209 paths)
210 210 _hg_paths
211 211 ;;
212 212 add)
213 213 _hg_status "u"
214 214 ;;
215 215 commit)
216 216 _hg_status "mar"
217 217 ;;
218 218 remove)
219 219 _hg_status "d"
220 220 ;;
221 221 forget)
222 222 _hg_status "a"
223 223 ;;
224 224 diff)
225 225 _hg_status "mar"
226 226 ;;
227 227 revert)
228 228 _hg_status "mard"
229 229 ;;
230 230 clone)
231 231 local count=$(_hg_count_non_option)
232 232 if [ $count = 1 ]; then
233 233 _hg_paths
234 234 fi
235 235 _hg_repos
236 236 ;;
237 237 debugindex|debugindexdot)
238 238 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
239 239 ;;
240 240 debugdata)
241 241 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
242 242 ;;
243 243 *)
244 244 return 1
245 245 ;;
246 246 esac
247 247
248 248 return 0
249 249 }
250 250
251 251 complete -o bashdefault -o default -F _hg hg 2>/dev/null \
252 252 || complete -o default -F _hg hg
253 253
254 254
255 255 # Completion for commands provided by extensions
256 256
257 257 # mq
258 258 _hg_ext_mq_patchlist()
259 259 {
260 260 local patches
261 261 patches=$("$hg" $1 2>/dev/null)
262 262 if [ $? -eq 0 ] && [ "$patches" ]; then
263 263 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
264 264 return 0
265 265 fi
266 266 return 1
267 267 }
268 268
269 269 _hg_ext_mq_queues()
270 270 {
271 271 local root=$("$hg" root 2>/dev/null)
272 272 local n
273 273 for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
274 274 # I think we're usually not interested in the regular "patches" queue
275 275 # so just filter it.
276 276 if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
277 277 COMPREPLY=(${COMPREPLY[@]:-} "$n")
278 278 fi
279 279 done
280 280 }
281 281
282 282 _hg_cmd_qpop()
283 283 {
284 284 if [[ "$prev" = @(-n|--name) ]]; then
285 285 _hg_ext_mq_queues
286 286 return
287 287 fi
288 288 _hg_ext_mq_patchlist qapplied
289 289 }
290 290
291 291 _hg_cmd_qpush()
292 292 {
293 293 if [[ "$prev" = @(-n|--name) ]]; then
294 294 _hg_ext_mq_queues
295 295 return
296 296 fi
297 297 _hg_ext_mq_patchlist qunapplied
298 298 }
299 299
300 300 _hg_cmd_qdelete()
301 301 {
302 302 local qcmd=qunapplied
303 303 if [[ "$prev" = @(-r|--rev) ]]; then
304 304 qcmd=qapplied
305 305 fi
306 306 _hg_ext_mq_patchlist $qcmd
307 307 }
308 308
309 309 _hg_cmd_qsave()
310 310 {
311 311 if [[ "$prev" = @(-n|--name) ]]; then
312 312 _hg_ext_mq_queues
313 313 return
314 314 fi
315 315 }
316 316
317 317 _hg_cmd_strip()
318 318 {
319 319 _hg_tags
320 320 }
321 321
322 322 _hg_cmd_qcommit()
323 323 {
324 324 local root=$("$hg" root 2>/dev/null)
325 325 # this is run in a sub-shell, so we can't use _hg_status
326 326 local files=$(cd "$root/.hg/patches" 2>/dev/null &&
327 327 "$hg" status -nmar 2>/dev/null)
328 328 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
329 329 }
330 330
331 _hg_cmd_qfold()
332 {
333 _hg_ext_mq_patchlist qunapplied
334 }
335
336 _hg_cmd_qrename()
337 {
338 _hg_ext_mq_patchlist qseries
339 }
340
341 _hg_cmd_qheader()
342 {
343 _hg_ext_mq_patchlist qseries
344 }
345
346 _hg_cmd_qclone()
347 {
348 local count=$(_hg_count_non_option)
349 if [ $count = 1 ]; then
350 _hg_paths
351 fi
352 _hg_repos
353 }
354
355 _hg_ext_mq_guards()
356 {
357 "$hg" qselect --series 2>/dev/null | sed -e 's/^.//'
358 }
359
360 _hg_cmd_qselect()
361 {
362 local guards=$(_hg_ext_mq_guards)
363 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$guards' -- "$cur"))
364 }
365
331 366
332 367 # hbisect
333 368 _hg_cmd_bisect()
334 369 {
335 370 local i subcmd
336 371
337 372 # find the sub-command
338 373 for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
339 374 if [[ ${COMP_WORDS[i]} != -* ]]; then
340 375 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
341 376 subcmd="${COMP_WORDS[i]}"
342 377 break
343 378 fi
344 379 fi
345 380 done
346 381
347 382 if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
348 383 COMPREPLY=(${COMPREPLY[@]:-}
349 384 $(compgen -W 'bad good help init next reset' -- "$cur"))
350 385 return
351 386 fi
352 387
353 388 case "$subcmd" in
354 389 good|bad)
355 390 _hg_tags
356 391 ;;
357 392 esac
358 393
359 394 return
360 395 }
361 396
362 397
363 398 # patchbomb
364 399 _hg_cmd_email()
365 400 {
366 401 case "$prev" in
367 402 -c|--cc|-t|--to|-f|--from|--bcc)
368 403 # we need an e-mail address. let the user provide a function
369 404 # to get them
370 405 if [ "$(type -t _hg_emails)" = function ]; then
371 406 local arg=to
372 407 if [[ "$prev" == @(-f|--from) ]]; then
373 408 arg=from
374 409 fi
375 410 local addresses=$(_hg_emails $arg)
376 411 COMPREPLY=(${COMPREPLY[@]:-}
377 412 $(compgen -W '$addresses' -- "$cur"))
378 413 fi
379 414 return
380 415 ;;
381 416 -m|--mbox)
382 417 # fallback to standard filename completion
383 418 return
384 419 ;;
385 420 -s|--subject)
386 421 # free form string
387 422 return
388 423 ;;
389 424 esac
390 425
391 426 _hg_tags
392 427 return
393 428 }
394 429
395 430
396 431 # gpg
397 432 _hg_cmd_sign()
398 433 {
399 434 _hg_tags
400 435 }
General Comments 0
You need to be logged in to leave comments. Login now