PageRenderTime 74ms CodeModel.GetById 66ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/bash_completion.d/mercurial

http://github.com/brinkman83/bashrc
#! | 573 lines | 505 code | 68 blank | 0 comment | 0 complexity | b6f333bd127bc79f3db3e86b6b38ccea MD5 | raw file
  1# bash completion for the Mercurial distributed SCM
  2
  3# Docs:
  4#
  5# If you source this file from your .bashrc, bash should be able to
  6# complete a command line that uses hg with all the available commands
  7# and options and sometimes even arguments.
  8#
  9# Mercurial allows you to define additional commands through extensions.
 10# Bash should be able to automatically figure out the name of these new
 11# commands and their options.  See below for how to define _hg_opt_foo
 12# and _hg_cmd_foo functions to fine-tune the completion for option and
 13# non-option arguments, respectively.
 14#
 15#
 16# Notes about completion for specific commands:
 17#
 18# - the completion function for the email command from the patchbomb
 19#   extension will try to call _hg_emails to get a list of e-mail
 20#   addresses.  It's up to the user to define this function.  For
 21#   example, put the addresses of the lists that you usually patchbomb
 22#   in ~/.patchbomb-to and the addresses that you usually use to send
 23#   the patchbombs in ~/.patchbomb-from and use something like this:
 24#
 25#      _hg_emails()
 26#      {
 27#          if [ -r ~/.patchbomb-$1 ]; then
 28#              cat ~/.patchbomb-$1
 29#          fi
 30#      }
 31#
 32#
 33# Writing completion functions for additional commands:
 34#
 35# If it exists, the function _hg_cmd_foo will be called without
 36# arguments to generate the completion candidates for the hg command
 37# "foo".  If the command receives some arguments that aren't options
 38# even though they start with a "-", you can define a function called
 39# _hg_opt_foo to generate the completion candidates.  If _hg_opt_foo
 40# doesn't return 0, regular completion for options is attempted.
 41#
 42# In addition to the regular completion variables provided by bash,
 43# the following variables are also set:
 44# - $hg - the hg program being used (e.g. /usr/bin/hg)
 45# - $cmd - the name of the hg command being completed
 46# - $cmd_index - the index of $cmd in $COMP_WORDS
 47# - $cur - the current argument being completed
 48# - $prev - the argument before $cur
 49# - $global_args - "|"-separated list of global options that accept
 50#                  an argument (e.g. '--cwd|-R|--repository')
 51# - $canonical - 1 if we canonicalized $cmd before calling the function
 52#                0 otherwise
 53#
 54
 55shopt -s extglob
 56
 57_hg_commands()
 58{
 59    local commands
 60    commands="$("$hg" debugcomplete "$cur" 2>/dev/null)" || commands=""
 61    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur"))
 62}
 63
 64_hg_paths()
 65{
 66    local paths="$("$hg" paths 2>/dev/null | sed -e 's/ = .*$//')"
 67    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur"))
 68}
 69
 70_hg_repos()
 71{
 72    local i
 73    for i in $(compgen -d -- "$cur"); do
 74	test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
 75    done
 76}
 77
 78_hg_status()
 79{
 80    local files="$("$hg" status -n$1 . 2>/dev/null)"
 81    local IFS=$'\n'
 82    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 83}
 84
 85_hg_tags()
 86{
 87    local tags="$("$hg" tags -q 2>/dev/null)"
 88    local IFS=$'\n'
 89    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$tags' -- "$cur"))
 90}
 91
 92_hg_branches()
 93{
 94    local branches="$("$hg" branches -q 2>/dev/null)"
 95    local IFS=$'\n'
 96    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$branches' -- "$cur"))
 97}
 98
 99# this is "kind of" ugly...
100_hg_count_non_option()
101{
102    local i count=0
103    local filters="$1"
104
105    for ((i=1; $i<=$COMP_CWORD; i++)); do
106	if [[ "${COMP_WORDS[i]}" != -* ]]; then
107	    if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
108		continue
109	    fi
110	    count=$(($count + 1))
111	fi
112    done
113
114    echo $(($count - 1))
115}
116
117_hg()
118{
119    local cur prev cmd cmd_index opts i
120    # global options that receive an argument
121    local global_args='--cwd|-R|--repository'
122    local hg="$1"
123    local canonical=0
124
125    COMPREPLY=()
126    cur="$2"
127    prev="$3"
128
129    # searching for the command
130    # (first non-option argument that doesn't follow a global option that
131    #  receives an argument)
132    for ((i=1; $i<=$COMP_CWORD; i++)); do
133	if [[ ${COMP_WORDS[i]} != -* ]]; then
134	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
135		cmd="${COMP_WORDS[i]}"
136		cmd_index=$i
137		break
138	    fi
139	fi
140    done
141
142    if [[ "$cur" == -* ]]; then
143	if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then
144	    return
145	fi
146
147	opts=$("$hg" debugcomplete --options "$cmd" 2>/dev/null)
148
149	COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
150	return
151    fi
152
153    # global options
154    case "$prev" in
155	-R|--repository)
156	    _hg_paths
157	    _hg_repos
158	    return
159	;;
160	--cwd)
161	    # Stick with default bash completion
162	    return
163	;;
164    esac
165
166    if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
167	_hg_commands
168	return
169    fi
170
171    # try to generate completion candidates for whatever command the user typed
172    local help
173    if _hg_command_specific; then
174	return
175    fi
176
177    # canonicalize the command name and try again
178    help=$("$hg" help "$cmd" 2>/dev/null)
179    if [ $? -ne 0 ]; then
180	# Probably either the command doesn't exist or it's ambiguous
181	return
182    fi
183    cmd=${help#hg }
184    cmd=${cmd%%[$' \n']*}
185    canonical=1
186    _hg_command_specific
187}
188
189_hg_command_specific()
190{
191    if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
192	"_hg_cmd_$cmd"
193	return 0
194    fi
195
196    if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
197	if [ $canonical = 1 ]; then
198	    _hg_tags
199	    _hg_branches
200	    return 0
201	elif [[ status != "$cmd"* ]]; then
202	    _hg_tags
203	    _hg_branches
204	    return 0
205	else
206	    return 1
207	fi
208    fi
209
210    case "$cmd" in
211	help)
212	    _hg_commands
213	;;
214	export)
215	    if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then
216		return 0
217	    fi
218	    _hg_tags
219	    _hg_branches
220	;;
221	manifest|update)
222	    _hg_tags
223	    _hg_branches
224	;;
225	pull|push|outgoing|incoming)
226	    _hg_paths
227	    _hg_repos
228	;;
229	paths)
230	    _hg_paths
231	;;
232	add)
233	    _hg_status "u"
234	;;
235	merge)
236	    _hg_tags
237	    _hg_branches
238	;;
239	commit)
240	    _hg_status "mar"
241	;;
242	remove)
243	    _hg_status "d"
244	;;
245	forget)
246	    _hg_status "a"
247	;;
248	diff)
249	    _hg_status "mar"
250	;;
251	revert)
252	    _hg_status "mard"
253	;;
254	clone)
255	    local count=$(_hg_count_non_option)
256	    if [ $count = 1 ]; then
257		_hg_paths
258	    fi
259	    _hg_repos
260	;;
261	debugindex|debugindexdot)
262	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
263	;;
264	debugdata)
265	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
266	;;
267	*)
268	    return 1
269	;;
270    esac
271
272    return 0
273}
274
275complete -o bashdefault -o default -F _hg hg 2>/dev/null \
276    || complete -o default -F _hg hg
277
278
279# Completion for commands provided by extensions
280
281# bookmarks
282_hg_bookmarks()
283{
284    local bookmarks="$("$hg" bookmarks --quiet 2>/dev/null )"
285    local IFS=$'\n'
286    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$bookmarks' -- "$cur"))
287}
288
289_hg_cmd_bookmarks()
290{
291    if [[ "$prev" = @(-d|--delete|-m|--rename) ]]; then
292        _hg_bookmarks
293        return
294    fi
295}
296
297# mq
298_hg_ext_mq_patchlist()
299{
300    local patches
301    patches=$("$hg" $1 2>/dev/null)
302    if [ $? -eq 0 ] && [ "$patches" ]; then
303	COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
304	return 0
305    fi
306    return 1
307}
308
309_hg_ext_mq_queues()
310{
311    local root=$("$hg" root 2>/dev/null)
312    local n
313    for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
314	# I think we're usually not interested in the regular "patches" queue
315	# so just filter it.
316	if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
317	    COMPREPLY=(${COMPREPLY[@]:-} "$n")
318	fi
319    done
320}
321
322_hg_cmd_qpop()
323{
324    if [[ "$prev" = @(-n|--name) ]]; then
325	_hg_ext_mq_queues
326	return
327    fi
328    _hg_ext_mq_patchlist qapplied
329}
330
331_hg_cmd_qpush()
332{
333    if [[ "$prev" = @(-n|--name) ]]; then
334	_hg_ext_mq_queues
335	return
336    fi
337    _hg_ext_mq_patchlist qunapplied
338}
339
340_hg_cmd_qgoto()
341{
342    if [[ "$prev" = @(-n|--name) ]]; then
343	_hg_ext_mq_queues
344	return
345    fi
346    _hg_ext_mq_patchlist qseries
347}
348
349_hg_cmd_qdelete()
350{
351    local qcmd=qunapplied
352    if [[ "$prev" = @(-r|--rev) ]]; then
353	qcmd=qapplied
354    fi
355    _hg_ext_mq_patchlist $qcmd
356}
357
358_hg_cmd_qfinish()
359{
360    if [[ "$prev" = @(-a|--applied) ]]; then
361	return
362    fi
363    _hg_ext_mq_patchlist qapplied
364}
365
366_hg_cmd_qsave()
367{
368    if [[ "$prev" = @(-n|--name) ]]; then
369	_hg_ext_mq_queues
370	return
371    fi
372}
373
374_hg_cmd_strip()
375{
376    _hg_tags
377    _hg_branches
378}
379
380_hg_cmd_qcommit()
381{
382    local root=$("$hg" root 2>/dev/null)
383    # this is run in a sub-shell, so we can't use _hg_status
384    local files=$(cd "$root/.hg/patches" 2>/dev/null &&
385                  "$hg" status -nmar 2>/dev/null)
386    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
387}
388
389_hg_cmd_qfold()
390{
391    _hg_ext_mq_patchlist qunapplied
392}
393
394_hg_cmd_qrename()
395{
396    _hg_ext_mq_patchlist qseries
397}
398
399_hg_cmd_qheader()
400{
401    _hg_ext_mq_patchlist qseries
402}
403
404_hg_cmd_qclone()
405{
406    local count=$(_hg_count_non_option)
407    if [ $count = 1 ]; then
408	_hg_paths
409    fi
410    _hg_repos
411}
412
413_hg_ext_mq_guards()
414{
415    "$hg" qselect --series 2>/dev/null | sed -e 's/^.//'
416}
417
418_hg_cmd_qselect()
419{
420    local guards=$(_hg_ext_mq_guards)
421    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$guards' -- "$cur"))
422}
423
424_hg_cmd_qguard()
425{
426    local prefix=''
427
428    if [[ "$cur" == +* ]]; then
429	prefix=+
430    elif [[ "$cur" == -* ]]; then
431	prefix=-
432    fi
433    local ncur=${cur#[-+]}
434
435    if ! [ "$prefix" ]; then
436	_hg_ext_mq_patchlist qseries
437	return
438    fi
439
440    local guards=$(_hg_ext_mq_guards)
441    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -P $prefix -W '$guards' -- "$ncur"))
442}
443
444_hg_opt_qguard()
445{
446    local i
447    for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
448	if [[ ${COMP_WORDS[i]} != -* ]]; then
449	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
450		_hg_cmd_qguard
451		return 0
452	    fi
453	elif [ "${COMP_WORDS[i]}" = -- ]; then
454	    _hg_cmd_qguard
455	    return 0
456	fi
457    done
458    return 1
459}
460
461
462# hbisect
463_hg_cmd_bisect()
464{
465    local i subcmd
466
467    # find the sub-command
468    for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
469	if [[ ${COMP_WORDS[i]} != -* ]]; then
470	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
471		subcmd="${COMP_WORDS[i]}"
472		break
473	    fi
474	fi
475    done
476
477    if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
478	COMPREPLY=(${COMPREPLY[@]:-}
479		   $(compgen -W 'bad good help init next reset' -- "$cur"))
480	return
481    fi
482
483    case "$subcmd" in
484	good|bad)
485	    _hg_tags
486	    _hg_branches
487	    ;;
488    esac
489
490    return
491}
492
493
494# patchbomb
495_hg_cmd_email()
496{
497    case "$prev" in
498	-c|--cc|-t|--to|-f|--from|--bcc)
499	    # we need an e-mail address. let the user provide a function
500	    # to get them
501	    if [ "$(type -t _hg_emails)" = function ]; then
502		local arg=to
503		if [[ "$prev" == @(-f|--from) ]]; then
504		    arg=from
505		fi
506		local addresses=$(_hg_emails $arg)
507		COMPREPLY=(${COMPREPLY[@]:-}
508			   $(compgen -W '$addresses' -- "$cur"))
509	    fi
510	    return
511	    ;;
512	-m|--mbox)
513	    # fallback to standard filename completion
514	    return
515	    ;;
516	-s|--subject)
517	    # free form string
518	    return
519	    ;;
520    esac
521
522    _hg_tags
523    _hg_branches
524    return
525}
526
527
528# gpg
529_hg_cmd_sign()
530{
531    _hg_tags
532    _hg_branches
533}
534
535
536# transplant
537_hg_cmd_transplant()
538{
539    case "$prev" in
540	-s|--source)
541	    _hg_paths
542	    _hg_repos
543	    return
544	    ;;
545	--filter)
546	    # standard filename completion
547	    return
548	    ;;
549    esac
550
551    # all other transplant options values and command parameters are revisions
552    _hg_tags
553    _hg_branches
554    return
555}
556
557# shelve
558_hg_shelves()
559{
560    local shelves="$("$hg" unshelve -l . 2>/dev/null)"
561    local IFS=$'\n'
562    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur"))
563}
564
565_hg_cmd_shelve()
566{
567    _hg_status "mard"
568}
569
570_hg_cmd_unshelve()
571{
572    _hg_shelves
573}