contrib/bash_completion
changeset 2041 077a2da7f1de
parent 2039 0c438fd25e6e
child 2695 c995d68333cf
equal deleted inserted replaced
2040:cd7711268774 2041:077a2da7f1de
       
     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.  If you also want to tell it how to
       
    12 # complete non-option arguments, see below for how to define an
       
    13 # _hg_cmd_foo function.
       
    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".
       
    38 #
       
    39 # In addition to the regular completion variables provided by bash,
       
    40 # the following variables are also set:
       
    41 # - $hg - the hg program being used (e.g. /usr/bin/hg)
       
    42 # - $cmd - the name of the hg command being completed
       
    43 # - $cmd_index - the index of $cmd in $COMP_WORDS
       
    44 # - $cur - the current argument being completed
       
    45 # - $prev - the argument before $cur
       
    46 # - $global_args - "|"-separated list of global options that accept
       
    47 #                  an argument (e.g. '--cwd|-R|--repository')
       
    48 # - $canonical - 1 if we canonicalized $cmd before calling the function
       
    49 #                0 otherwise
       
    50 # 
       
    51 
     1 shopt -s extglob
    52 shopt -s extglob
     2 
    53 
     3 _hg_commands()
    54 _hg_commands()
     4 {
    55 {
     5     local commands
    56     local commands
    52     echo $(($count - 1))
   103     echo $(($count - 1))
    53 }
   104 }
    54 
   105 
    55 _hg()
   106 _hg()
    56 {
   107 {
    57     local cur prev cmd opts i
   108     local cur prev cmd cmd_index opts i
    58     # global options that receive an argument
   109     # global options that receive an argument
    59     local global_args='--cwd|-R|--repository'
   110     local global_args='--cwd|-R|--repository'
    60     local hg="$1"
   111     local hg="$1"
    61 
   112 
    62     COMPREPLY=()
   113     COMPREPLY=()
    68     #  receives an argument)
   119     #  receives an argument)
    69     for ((i=1; $i<=$COMP_CWORD; i++)); do
   120     for ((i=1; $i<=$COMP_CWORD; i++)); do
    70 	if [[ ${COMP_WORDS[i]} != -* ]]; then
   121 	if [[ ${COMP_WORDS[i]} != -* ]]; then
    71 	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
   122 	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
    72 		cmd="${COMP_WORDS[i]}"
   123 		cmd="${COMP_WORDS[i]}"
       
   124 		cmd_index=$i
    73 		break
   125 		break
    74 	    fi
   126 	    fi
    75 	fi
   127 	fi
    76     done
   128     done
    77 
   129 
   118     _hg_command_specific
   170     _hg_command_specific
   119 }
   171 }
   120 
   172 
   121 _hg_command_specific()
   173 _hg_command_specific()
   122 {
   174 {
       
   175     if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
       
   176 	"_hg_cmd_$cmd"
       
   177 	return 0
       
   178     fi
       
   179 
   123     if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
   180     if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
   124 	if [ $canonical = 1 ]; then
   181 	if [ $canonical = 1 ]; then
   125 	    _hg_tags
   182 	    _hg_tags
   126 	    return 0
   183 	    return 0
   127 	elif [[ status != "$cmd"* ]]; then
   184 	elif [[ status != "$cmd"* ]]; then
   185     return 0
   242     return 0
   186 }
   243 }
   187 
   244 
   188 complete -o bashdefault -o default -F _hg hg 2>/dev/null \
   245 complete -o bashdefault -o default -F _hg hg 2>/dev/null \
   189     || complete -o default -F _hg hg
   246     || complete -o default -F _hg hg
       
   247 
       
   248 
       
   249 # Completion for commands provided by extensions
       
   250 
       
   251 # mq
       
   252 _hg_ext_mq_patchlist()
       
   253 {
       
   254     local patches=$("$hg" $1 2>/dev/null)
       
   255     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
       
   256 }
       
   257 
       
   258 _hg_ext_mq_queues()
       
   259 {
       
   260     local root=$("$hg" root 2>/dev/null)
       
   261     local n
       
   262     for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
       
   263 	# I think we're usually not interested in the regular "patches" queue
       
   264 	# so just filter it.
       
   265 	if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
       
   266 	    COMPREPLY=(${COMPREPLY[@]:-} "$n")
       
   267 	fi
       
   268     done
       
   269 }
       
   270 
       
   271 _hg_cmd_qpop()
       
   272 {
       
   273     if [[ "$prev" = @(-n|--name) ]]; then
       
   274 	_hg_ext_mq_queues
       
   275 	return
       
   276     fi
       
   277     _hg_ext_mq_patchlist qapplied
       
   278 }
       
   279 
       
   280 _hg_cmd_qpush()
       
   281 {
       
   282     if [[ "$prev" = @(-n|--name) ]]; then
       
   283 	_hg_ext_mq_queues
       
   284 	return
       
   285     fi
       
   286     _hg_ext_mq_patchlist qunapplied
       
   287 }
       
   288 
       
   289 _hg_cmd_qdelete()
       
   290 {
       
   291     _hg_ext_mq_patchlist qseries
       
   292 }
       
   293 
       
   294 _hg_cmd_qsave()
       
   295 {
       
   296     if [[ "$prev" = @(-n|--name) ]]; then
       
   297 	_hg_ext_mq_queues
       
   298 	return
       
   299     fi
       
   300 }
       
   301 
       
   302 _hg_cmd_strip()
       
   303 {
       
   304     _hg_tags
       
   305 }
       
   306 
       
   307 _hg_cmd_qcommit()
       
   308 {
       
   309     local root=$("$hg" root 2>/dev/null)
       
   310     # this is run in a sub-shell, so we can't use _hg_status
       
   311     local files=$(cd "$root/.hg/patches" 2>/dev/null &&
       
   312                   "$hg" status -nmar 2>/dev/null)
       
   313     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
       
   314 }
       
   315 
       
   316 
       
   317 # hbisect
       
   318 _hg_cmd_bisect()
       
   319 {
       
   320     local i subcmd
       
   321 
       
   322     # find the sub-command
       
   323     for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
       
   324 	if [[ ${COMP_WORDS[i]} != -* ]]; then
       
   325 	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
       
   326 		subcmd="${COMP_WORDS[i]}"
       
   327 		break
       
   328 	    fi
       
   329 	fi
       
   330     done
       
   331 
       
   332     if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
       
   333 	COMPREPLY=(${COMPREPLY[@]:-} 
       
   334 		   $(compgen -W 'bad good help init next reset' -- "$cur"))
       
   335 	return
       
   336     fi
       
   337 
       
   338     case "$subcmd" in
       
   339 	good|bad)
       
   340 	    _hg_tags
       
   341 	    ;;
       
   342     esac
       
   343 
       
   344     return
       
   345 }
       
   346 
       
   347 
       
   348 # patchbomb
       
   349 _hg_cmd_email()
       
   350 {
       
   351     case "$prev" in
       
   352 	-c|--cc|-t|--to|-f|--from)
       
   353 	    # we need an e-mail address. let the user provide a function 
       
   354 	    # to get them
       
   355 	    if [ "$(type -t _hg_emails)" = function ]; then
       
   356 		local arg=to
       
   357 		if [[ "$prev" == @(-f|--from) ]]; then
       
   358 		    arg=from
       
   359 		fi
       
   360 		local addresses=$(_hg_emails $arg)
       
   361 		COMPREPLY=(${COMPREPLY[@]:-}
       
   362 			   $(compgen -W '$addresses' -- "$cur"))
       
   363 	    fi
       
   364 	    return
       
   365 	    ;;
       
   366 	-m|--mbox)
       
   367 	    # fallback to standard filename completion
       
   368 	    return
       
   369 	    ;;
       
   370 	-s|--subject)
       
   371 	    # free form string
       
   372 	    return
       
   373 	    ;;
       
   374     esac
       
   375 
       
   376     _hg_tags
       
   377     return
       
   378 }
       
   379 
       
   380 
       
   381 # gpg
       
   382 _hg_cmd_sign()
       
   383 {
       
   384     _hg_tags
       
   385 }