[PATCH 2 of 3] bash_completion: completion for commands provided by extensions

Alexis S. L. Carvalho alexis at cecm.usp.br
Wed Mar 29 22:21:58 UTC 2006


# HG changeset patch
# User Alexis S. L. Carvalho <alexis at cecm.usp.br>
# Node ID dae81ada6e11dabb9e17f7cc6b3ab90ee1aaeacf
# Parent  e8b0c3be0301d2dfa17bc181297ee4a4d6a0a965
bash_completion: completion for commands provided by extensions

Make the bash_completion function call _hg_cmd_$cmd to generate
completion candidates for $cmd if that function exists.

Add basic completion functions for:

- mq:
  - qpop
  - qpush
  - qdelete
  - qsave
  - qcommit
  - strip

- hbisect:
  - bisect

- patchbomb:
  - email

- gpg:
  - sign

diff -r e8b0c3be0301 -r dae81ada6e11 contrib/bash_completion
--- a/contrib/bash_completion	Sun Mar 26 18:44:56 2006 -0300
+++ b/contrib/bash_completion	Sun Mar 26 19:49:30 2006 -0300
@@ -67,7 +67,7 @@ _hg_count_non_option()
 
 _hg()
 {
-    local cur prev cmd opts i
+    local cur prev cmd cmd_index opts i
     # global options that receive an argument
     local global_args='--cwd|-R|--repository'
     local hg="$1"
@@ -83,6 +83,7 @@ _hg()
 	if [[ ${COMP_WORDS[i]} != -* ]]; then
 	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
 		cmd="${COMP_WORDS[i]}"
+		cmd_index=$i
 		break
 	    fi
 	fi
@@ -133,6 +134,11 @@ _hg()
 
 _hg_command_specific()
 {
+    if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
+	"_hg_cmd_$cmd"
+	return 0
+    fi
+
     if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
 	if [ $canonical = 1 ]; then
 	    _hg_tags
diff -r e8b0c3be0301 -r dae81ada6e11 contrib/bash_completion.ext
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/bash_completion.ext	Sun Mar 26 19:49:30 2006 -0300
@@ -0,0 +1,172 @@
+# bash completion for extensions distributed with mercurial
+
+# Docs:
+#
+# The completion function for the email command from the patchbomb
+# extension will try to call _hg_emails to get a 
+# list of e-mail addresses.  It's up to the user to define this 
+# function.  For example, put the addresses of the lists that you
+# usually patchbomb in ~/.patchbomb-to and the addresses that you
+# usually use to send the patchbombs in ~/.patchbomb-from and use
+# something like this:
+#
+# _hg_emails()
+# {
+#     if [ -r ~/.patchbomb-$1 ]; then
+#         cat ~/.patchbomb-$1
+#     fi
+# }
+# 
+
+# Writing completion functions for additional commands:
+#
+# The function _hg_cmd_foo will be called to generate the completion
+# candidates for the hg command "foo".
+#
+# In addition to the regular completion variables provided by bash,
+# the following variables are also set:
+# - $hg - the hg program being used (e.g. /usr/bin/hg)
+# - $cmd - the name of the hg command being completed
+# - $cmd_index - the index of $cmd in $COMP_WORDS
+# - $cur - the current argument being completed
+# - $prev - the argument before $cur
+# - $global_args - "|"-separated list of global options that accept
+#                  an argument (e.g. '--cwd|-R|--repository')
+# - $canonical - 1 if we canonicalized $cmd before calling the function
+#                0 otherwise
+# - $help - only set if $canonical = 1 . Contains the output of hg help $cmd
+# 
+
+# mq
+_hg_ext_mq_patchlist()
+{
+    local patches=$("$hg" $1 2>/dev/null)
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
+}
+
+_hg_ext_mq_queues()
+{
+    local root=$("$hg" root 2>/dev/null)
+    local n
+    for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
+	# I think we're usually not interested in the regular "patches" queue
+	# so just filter it.
+	if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
+	    COMPREPLY=(${COMPREPLY[@]:-} "$n")
+	fi
+    done
+}
+
+_hg_cmd_qpop()
+{
+    if [[ "$prev" = @(-n|--name) ]]; then
+	_hg_ext_mq_queues
+	return
+    fi
+    _hg_ext_mq_patchlist qapplied
+}
+
+_hg_cmd_qpush()
+{
+    if [[ "$prev" = @(-n|--name) ]]; then
+	_hg_ext_mq_queues
+	return
+    fi
+    _hg_ext_mq_patchlist qunapplied
+}
+
+_hg_cmd_qdelete()
+{
+    _hg_ext_mq_patchlist qseries
+}
+
+_hg_cmd_qsave()
+{
+    if [[ "$prev" = @(-n|--name) ]]; then
+	_hg_ext_mq_queues
+	return
+    fi
+}
+
+_hg_cmd_strip()
+{
+    _hg_tags
+}
+
+_hg_cmd_qcommit()
+{
+    local root=$("$hg" root 2>/dev/null)
+    # this is run in a sub-shell, so we can't use _hg_status
+    local files=$(cd "$root/.hg/patches" 2>/dev/null &&
+                  "$hg" status -nmar 2>/dev/null)
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
+}
+
+# hbisect
+_hg_cmd_bisect()
+{
+    local i subcmd
+
+    # find the sub-command
+    for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
+	if [[ ${COMP_WORDS[i]} != -* ]]; then
+	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
+		subcmd="${COMP_WORDS[i]}"
+		break
+	    fi
+	fi
+    done
+
+    if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
+	COMPREPLY=(${COMPREPLY[@]:-} 
+		   $(compgen -W 'bad good help init next reset' -- "$cur"))
+	return
+    fi
+
+    case "$subcmd" in
+	good|bad)
+	    _hg_tags
+	    ;;
+    esac
+
+    return
+}
+
+
+# patchbomb
+_hg_cmd_email()
+{
+    case "$prev" in
+	-c|--cc|-t|--to|-f|--from)
+	    # we need an e-mail address. let the user provide a function 
+	    # to get them
+	    if [ "$(type -t _hg_emails)" = function ]; then
+		local arg=to
+		if [[ "$prev" == @(-f|--from) ]]; then
+		    arg=from
+		fi
+		local addresses=$(_hg_emails $arg)
+		COMPREPLY=(${COMPREPLY[@]:-}
+			   $(compgen -W '$addresses' -- "$cur"))
+	    fi
+	    return
+	    ;;
+	-m|--mbox)
+	    # fallback to standard filename completion
+	    return
+	    ;;
+	-s|--subject)
+	    # free form string
+	    return
+	    ;;
+    esac
+
+    _hg_tags
+    return
+}
+
+# gpg
+_hg_cmd_sign()
+{
+    _hg_tags
+}



More information about the Mercurial mailing list