##// END OF EJS Templates
bash_completion: do not use aliased hg if it sources a script (issue6308)...
Peter Arrenbrecht -
r45338:f71c8eea stable
parent child Browse files
Show More
@@ -1,656 +1,659 b''
1 1 # bash completion for the Mercurial distributed SCM -*- sh -*-
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. See below for how to define _hg_opt_foo
12 12 # and _hg_cmd_foo functions to fine-tune the completion for option and
13 13 # non-option arguments, respectively.
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". If the command receives some arguments that aren't options
38 38 # even though they start with a "-", you can define a function called
39 39 # _hg_opt_foo to generate the completion candidates. If _hg_opt_foo
40 40 # doesn't return 0, regular completion for options is attempted.
41 41 #
42 42 # In addition to the regular completion variables provided by bash,
43 43 # the following variables are also set:
44 44 # - $hg - the hg program being used (e.g. /usr/bin/hg)
45 45 # - $cmd - the name of the hg command being completed
46 46 # - $cmd_index - the index of $cmd in $COMP_WORDS
47 47 # - $cur - the current argument being completed
48 48 # - $prev - the argument before $cur
49 49 # - $global_args - "|"-separated list of global options that accept
50 50 # an argument (e.g. '--cwd|-R|--repository')
51 51 # - $canonical - 1 if we canonicalized $cmd before calling the function
52 52 # 0 otherwise
53 53 #
54 54
55 55 shopt -s extglob
56 56
57 57 _hg_cmd()
58 58 {
59 59 HGPLAIN=1 "$hg" "$@" 2>/dev/null
60 60 }
61 61
62 62 _hg_commands()
63 63 {
64 64 local commands
65 65 commands="$(HGPLAINEXCEPT=alias _hg_cmd debugcomplete "$cur")" || commands=""
66 66 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur"))
67 67 }
68 68
69 69 _hg_paths()
70 70 {
71 71 local paths="$(_hg_cmd paths -q)"
72 72 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur"))
73 73 }
74 74
75 75 _hg_repos()
76 76 {
77 77 local i
78 78 for i in $(compgen -d -- "$cur"); do
79 79 test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
80 80 done
81 81 }
82 82
83 83 _hg_debugpathcomplete()
84 84 {
85 85 local files="$(_hg_cmd debugpathcomplete $1 "$cur")"
86 86 local IFS=$'\n'
87 87 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
88 88 }
89 89
90 90 _hg_status()
91 91 {
92 92 if [ -z "$HGCOMPLETE_NOSTATUS" ]; then
93 93 local files="$(_hg_cmd status -n$1 "glob:$cur**")"
94 94 local IFS=$'\n'
95 95 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
96 96 fi
97 97 }
98 98
99 99 _hg_branches()
100 100 {
101 101 local branches="$(_hg_cmd branches -q)"
102 102 local IFS=$'\n'
103 103 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$branches' -- "$cur"))
104 104 }
105 105
106 106 _hg_bookmarks()
107 107 {
108 108 local bookmarks="$(_hg_cmd bookmarks -q)"
109 109 local IFS=$'\n'
110 110 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$bookmarks' -- "$cur"))
111 111 }
112 112
113 113 _hg_labels()
114 114 {
115 115 local labels="$(_hg_cmd debugnamecomplete "$cur")"
116 116 local IFS=$'\n'
117 117 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur"))
118 118 }
119 119
120 120 # this is "kind of" ugly...
121 121 _hg_count_non_option()
122 122 {
123 123 local i count=0
124 124 local filters="$1"
125 125
126 126 for ((i=1; $i<=$COMP_CWORD; i++)); do
127 127 if [[ "${COMP_WORDS[i]}" != -* ]]; then
128 128 if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
129 129 continue
130 130 fi
131 131 count=$(($count + 1))
132 132 fi
133 133 done
134 134
135 135 echo $(($count - 1))
136 136 }
137 137
138 138 _hg_fix_wordlist()
139 139 {
140 140 local LASTCHAR=' '
141 141 if [ ${#COMPREPLY[@]} = 1 ]; then
142 142 [ -d "$COMPREPLY" ] && LASTCHAR=/
143 143 COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR")
144 144 else
145 145 for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
146 146 [ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
147 147 done
148 148 fi
149 149 }
150 150
151 151 _hg()
152 152 {
153 153 local cur prev cmd cmd_index opts i aliashg
154 154 # global options that receive an argument
155 155 local global_args='--cwd|-R|--repository|--color|--config|--encoding|--encodingmode|--pager'
156 156 local hg="$1"
157 157 local canonical=0
158 158
159 159 aliashg=$(alias $hg 2>/dev/null)
160 160 if [[ -n "$aliashg" ]]; then
161 161 aliashg=${aliashg#"alias $hg='"}
162 162 aliashg=${aliashg%"'"}
163 hg=$aliashg
163 # `source`d aliases break completion, so ignore them
164 if [[ "${aliashg:0:7}" != "source " ]]; then
165 hg=$aliashg
166 fi
164 167 fi
165 168
166 169 COMPREPLY=()
167 170 cur="$2"
168 171 prev="$3"
169 172
170 173 # searching for the command
171 174 # (first non-option argument that doesn't follow a global option that
172 175 # receives an argument)
173 176 for ((i=1; $i<=$COMP_CWORD; i++)); do
174 177 if [[ ${COMP_WORDS[i]} != -* ]]; then
175 178 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
176 179 cmd="${COMP_WORDS[i]}"
177 180 cmd_index=$i
178 181 break
179 182 fi
180 183 fi
181 184 done
182 185
183 186 if [[ "$cur" == -* ]]; then
184 187 if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then
185 188 _hg_fix_wordlist
186 189 return
187 190 fi
188 191
189 192 opts=$(HGPLAINEXCEPT=alias _hg_cmd debugcomplete --options "$cmd")
190 193
191 194 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
192 195 _hg_fix_wordlist
193 196 return
194 197 fi
195 198
196 199 # global options
197 200 case "$prev" in
198 201 -R|--repository)
199 202 _hg_paths
200 203 _hg_repos
201 204 _hg_fix_wordlist
202 205 return
203 206 ;;
204 207 --cwd)
205 208 # Stick with default bash completion
206 209 _hg_fix_wordlist
207 210 return
208 211 ;;
209 212 --color)
210 213 local choices='true false yes no always auto never debug'
211 214 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$choices' -- "$cur"))
212 215 _hg_fix_wordlist
213 216 return
214 217 ;;
215 218 --pager)
216 219 local choices='true false yes no always auto never'
217 220 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$choices' -- "$cur"))
218 221 _hg_fix_wordlist
219 222 return
220 223 ;;
221 224 esac
222 225
223 226 if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
224 227 _hg_commands
225 228 _hg_fix_wordlist
226 229 return
227 230 fi
228 231
229 232 # try to generate completion candidates for whatever command the user typed
230 233 local help
231 234 if _hg_command_specific; then
232 235 _hg_fix_wordlist
233 236 return
234 237 fi
235 238
236 239 # canonicalize the command name and try again
237 240 help=$(_hg_cmd help "$cmd")
238 241 if [ $? -ne 0 ]; then
239 242 # Probably either the command doesn't exist or it's ambiguous
240 243 return
241 244 fi
242 245 cmd=${help#hg }
243 246 cmd=${cmd%%[$' \n']*}
244 247 canonical=1
245 248 _hg_command_specific
246 249 _hg_fix_wordlist
247 250 }
248 251
249 252 _hg_command_specific()
250 253 {
251 254 if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
252 255 "_hg_cmd_$cmd"
253 256 return 0
254 257 fi
255 258
256 259 if [ "$cmd" != status ]; then
257 260 case "$prev" in
258 261 -r|--rev)
259 262 if [[ $canonical = 1 || status != "$cmd"* ]]; then
260 263 _hg_labels
261 264 return 0
262 265 fi
263 266 return 1
264 267 ;;
265 268 -B|--bookmark)
266 269 if [[ $canonical = 1 || status != "$cmd"* ]]; then
267 270 _hg_bookmarks
268 271 return 0
269 272 fi
270 273 return 1
271 274 ;;
272 275 -b|--branch)
273 276 if [[ $canonical = 1 || status != "$cmd"* ]]; then
274 277 _hg_branches
275 278 return 0
276 279 fi
277 280 return 1
278 281 ;;
279 282 esac
280 283 fi
281 284
282 285 local aliascmd=$(_hg_cmd showconfig alias.$cmd | awk '{print $1}')
283 286 [ -n "$aliascmd" ] && cmd=$aliascmd
284 287
285 288 case "$cmd" in
286 289 help)
287 290 _hg_commands
288 291 ;;
289 292 export)
290 293 if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then
291 294 return 0
292 295 fi
293 296 _hg_labels
294 297 ;;
295 298 manifest|update|up|checkout|co)
296 299 _hg_labels
297 300 ;;
298 301 pull|push|outgoing|incoming)
299 302 _hg_paths
300 303 _hg_repos
301 304 ;;
302 305 paths)
303 306 _hg_paths
304 307 ;;
305 308 add)
306 309 _hg_status "u"
307 310 ;;
308 311 merge)
309 312 _hg_labels
310 313 ;;
311 314 commit|ci|record|amend)
312 315 _hg_status "mar"
313 316 ;;
314 317 remove|rm)
315 318 _hg_debugpathcomplete -n
316 319 ;;
317 320 forget)
318 321 _hg_debugpathcomplete -fa
319 322 ;;
320 323 diff)
321 324 _hg_status "mar"
322 325 ;;
323 326 revert)
324 327 _hg_status "mard"
325 328 ;;
326 329 clone)
327 330 local count=$(_hg_count_non_option)
328 331 if [ $count = 1 ]; then
329 332 _hg_paths
330 333 fi
331 334 _hg_repos
332 335 ;;
333 336 debugindex|debugindexdot)
334 337 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
335 338 ;;
336 339 debugdata)
337 340 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
338 341 ;;
339 342 *)
340 343 return 1
341 344 ;;
342 345 esac
343 346
344 347 return 0
345 348 }
346 349
347 350 complete -o bashdefault -o default -o nospace -F _hg hg \
348 351 || complete -o default -o nospace -F _hg hg
349 352
350 353
351 354 # Completion for commands provided by extensions
352 355
353 356 # bookmarks
354 357 _hg_cmd_bookmarks()
355 358 {
356 359 _hg_bookmarks
357 360 return
358 361 }
359 362
360 363 # mq
361 364 _hg_ext_mq_patchlist()
362 365 {
363 366 local patches
364 367 patches=$(_hg_cmd $1)
365 368 if [ $? -eq 0 ] && [ "$patches" ]; then
366 369 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
367 370 return 0
368 371 fi
369 372 return 1
370 373 }
371 374
372 375 _hg_ext_mq_queues()
373 376 {
374 377 local root=$(_hg_cmd root)
375 378 local n
376 379 for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
377 380 # I think we're usually not interested in the regular "patches" queue
378 381 # so just filter it.
379 382 if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
380 383 COMPREPLY=(${COMPREPLY[@]:-} "$n")
381 384 fi
382 385 done
383 386 }
384 387
385 388 _hg_cmd_qpop()
386 389 {
387 390 if [[ "$prev" = @(-n|--name) ]]; then
388 391 _hg_ext_mq_queues
389 392 return
390 393 fi
391 394 _hg_ext_mq_patchlist qapplied
392 395 }
393 396
394 397 _hg_cmd_qpush()
395 398 {
396 399 if [[ "$prev" = @(-n|--name) ]]; then
397 400 _hg_ext_mq_queues
398 401 return
399 402 fi
400 403 _hg_ext_mq_patchlist qunapplied
401 404 }
402 405
403 406 _hg_cmd_qgoto()
404 407 {
405 408 if [[ "$prev" = @(-n|--name) ]]; then
406 409 _hg_ext_mq_queues
407 410 return
408 411 fi
409 412 _hg_ext_mq_patchlist qseries
410 413 }
411 414
412 415 _hg_cmd_qdelete()
413 416 {
414 417 local qcmd=qunapplied
415 418 if [[ "$prev" = @(-r|--rev) ]]; then
416 419 qcmd=qapplied
417 420 fi
418 421 _hg_ext_mq_patchlist $qcmd
419 422 }
420 423
421 424 _hg_cmd_qfinish()
422 425 {
423 426 if [[ "$prev" = @(-a|--applied) ]]; then
424 427 return
425 428 fi
426 429 _hg_ext_mq_patchlist qapplied
427 430 }
428 431
429 432 _hg_cmd_qsave()
430 433 {
431 434 if [[ "$prev" = @(-n|--name) ]]; then
432 435 _hg_ext_mq_queues
433 436 return
434 437 fi
435 438 }
436 439
437 440 _hg_cmd_rebase() {
438 441 if [[ "$prev" = @(-s|--source|-d|--dest|-b|--base|-r|--rev) ]]; then
439 442 _hg_labels
440 443 return
441 444 fi
442 445 }
443 446
444 447 _hg_cmd_strip()
445 448 {
446 449 if [[ "$prev" = @(-B|--bookmark) ]]; then
447 450 _hg_bookmarks
448 451 return
449 452 fi
450 453 _hg_labels
451 454 }
452 455
453 456 _hg_cmd_qcommit()
454 457 {
455 458 local root=$(_hg_cmd root)
456 459 # this is run in a sub-shell, so we can't use _hg_status
457 460 local files=$(cd "$root/.hg/patches" && _hg_cmd status -nmar)
458 461 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
459 462 }
460 463
461 464 _hg_cmd_qfold()
462 465 {
463 466 _hg_ext_mq_patchlist qunapplied
464 467 }
465 468
466 469 _hg_cmd_qrename()
467 470 {
468 471 _hg_ext_mq_patchlist qseries
469 472 }
470 473
471 474 _hg_cmd_qheader()
472 475 {
473 476 _hg_ext_mq_patchlist qseries
474 477 }
475 478
476 479 _hg_cmd_qclone()
477 480 {
478 481 local count=$(_hg_count_non_option)
479 482 if [ $count = 1 ]; then
480 483 _hg_paths
481 484 fi
482 485 _hg_repos
483 486 }
484 487
485 488 _hg_ext_mq_guards()
486 489 {
487 490 _hg_cmd qselect --series | sed -e 's/^.//'
488 491 }
489 492
490 493 _hg_cmd_qselect()
491 494 {
492 495 local guards=$(_hg_ext_mq_guards)
493 496 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$guards' -- "$cur"))
494 497 }
495 498
496 499 _hg_cmd_qguard()
497 500 {
498 501 local prefix=''
499 502
500 503 if [[ "$cur" == +* ]]; then
501 504 prefix=+
502 505 elif [[ "$cur" == -* ]]; then
503 506 prefix=-
504 507 fi
505 508 local ncur=${cur#[-+]}
506 509
507 510 if ! [ "$prefix" ]; then
508 511 _hg_ext_mq_patchlist qseries
509 512 return
510 513 fi
511 514
512 515 local guards=$(_hg_ext_mq_guards)
513 516 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -P $prefix -W '$guards' -- "$ncur"))
514 517 }
515 518
516 519 _hg_opt_qguard()
517 520 {
518 521 local i
519 522 for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
520 523 if [[ ${COMP_WORDS[i]} != -* ]]; then
521 524 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
522 525 _hg_cmd_qguard
523 526 return 0
524 527 fi
525 528 elif [ "${COMP_WORDS[i]}" = -- ]; then
526 529 _hg_cmd_qguard
527 530 return 0
528 531 fi
529 532 done
530 533 return 1
531 534 }
532 535
533 536 _hg_cmd_qqueue()
534 537 {
535 538 local q
536 539 local queues
537 540 local opts="--list --create --rename --delete --purge"
538 541
539 542 queues=$( _hg_cmd qqueue --quiet )
540 543
541 544 COMPREPLY=( $( compgen -W "${opts} ${queues}" "${cur}" ) )
542 545 }
543 546
544 547
545 548 # hbisect
546 549 _hg_cmd_bisect()
547 550 {
548 551 local i subcmd
549 552
550 553 # find the sub-command
551 554 for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
552 555 if [[ ${COMP_WORDS[i]} != -* ]]; then
553 556 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
554 557 subcmd="${COMP_WORDS[i]}"
555 558 break
556 559 fi
557 560 fi
558 561 done
559 562
560 563 if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
561 564 COMPREPLY=(${COMPREPLY[@]:-}
562 565 $(compgen -W 'bad good help init next reset' -- "$cur"))
563 566 return
564 567 fi
565 568
566 569 case "$subcmd" in
567 570 good|bad)
568 571 _hg_labels
569 572 ;;
570 573 esac
571 574
572 575 return
573 576 }
574 577
575 578
576 579 # patchbomb
577 580 _hg_cmd_email()
578 581 {
579 582 case "$prev" in
580 583 -c|--cc|-t|--to|-f|--from|--bcc)
581 584 # we need an e-mail address. let the user provide a function
582 585 # to get them
583 586 if [ "$(type -t _hg_emails)" = function ]; then
584 587 local arg=to
585 588 if [[ "$prev" == @(-f|--from) ]]; then
586 589 arg=from
587 590 fi
588 591 local addresses=$(_hg_emails $arg)
589 592 COMPREPLY=(${COMPREPLY[@]:-}
590 593 $(compgen -W '$addresses' -- "$cur"))
591 594 fi
592 595 return
593 596 ;;
594 597 -m|--mbox)
595 598 # fallback to standard filename completion
596 599 return
597 600 ;;
598 601 -s|--subject)
599 602 # free form string
600 603 return
601 604 ;;
602 605 esac
603 606
604 607 _hg_labels
605 608 return
606 609 }
607 610
608 611
609 612 # gpg
610 613 _hg_cmd_sign()
611 614 {
612 615 _hg_labels
613 616 }
614 617
615 618
616 619 # transplant
617 620 _hg_cmd_transplant()
618 621 {
619 622 case "$prev" in
620 623 -s|--source)
621 624 _hg_paths
622 625 _hg_repos
623 626 return
624 627 ;;
625 628 --filter)
626 629 # standard filename completion
627 630 return
628 631 ;;
629 632 esac
630 633
631 634 # all other transplant options values and command parameters are revisions
632 635 _hg_labels
633 636 return
634 637 }
635 638
636 639 # shelve
637 640 _hg_shelves()
638 641 {
639 642 local shelves="$(_hg_cmd shelve -ql)"
640 643 local IFS=$'\n'
641 644 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur"))
642 645 }
643 646
644 647 _hg_cmd_shelve()
645 648 {
646 649 if [[ "$prev" = @(-d|--delete|-l|--list|-p|--patch|--stat) ]]; then
647 650 _hg_shelves
648 651 else
649 652 _hg_status "mard"
650 653 fi
651 654 }
652 655
653 656 _hg_cmd_unshelve()
654 657 {
655 658 _hg_shelves
656 659 }
General Comments 0
You need to be logged in to leave comments. Login now