about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-10-14 15:05:40 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-10-14 15:05:40 +0000
commit9597b7505ab1cf64c246b4a32e14b0602c36b1b2 (patch)
tree97583fa3e3b2c9bcdc3d1f2dfa2baed17d0924c5
parentc0482994a91094dc8e89bddefdeabf36829e9eea (diff)
downloadzsh-9597b7505ab1cf64c246b4a32e14b0602c36b1b2.tar.gz
zsh-9597b7505ab1cf64c246b4a32e14b0602c36b1b2.tar.xz
zsh-9597b7505ab1cf64c246b4a32e14b0602c36b1b2.zip
manual/8249
-rw-r--r--Completion/Builtins/_nothing3
-rw-r--r--Completion/Core/_description2
-rw-r--r--Completion/Core/_files9
-rw-r--r--Completion/Core/_main_complete20
-rw-r--r--Completion/Core/_message5
-rw-r--r--Completion/Core/_multi_parts53
-rw-r--r--Completion/Core/_path_files38
-rw-r--r--Completion/Core/_sep_parts12
-rw-r--r--Doc/Zsh/compctl.yo7
-rw-r--r--Doc/Zsh/compsys.yo49
-rw-r--r--Src/Zle/compctl.c87
-rw-r--r--Src/Zle/compctl.mdd2
12 files changed, 210 insertions, 77 deletions
diff --git a/Completion/Builtins/_nothing b/Completion/Builtins/_nothing
new file mode 100644
index 000000000..35a2558cc
--- /dev/null
+++ b/Completion/Builtins/_nothing
@@ -0,0 +1,3 @@
+#compdef true false
+
+_message 'no argument or option'
diff --git a/Completion/Core/_description b/Completion/Core/_description
index a19a8373c..107be5cd6 100644
--- a/Completion/Core/_description
+++ b/Completion/Core/_description
@@ -7,6 +7,8 @@ if [[ "$1" = -[VJ]* ]]; then
   shift
 fi
 
+_lastdescr=( "$_lastdescr[@]" "$2" )
+
 if [[ -n "$compconfig[group_matches]" ]]; then
   if [[ -n "$compconfig[description_format]" ]]; then
     eval "$1=($gropt ${(q)2} -X ${(q)compconfig[description_format]//\\%d/$2})"
diff --git a/Completion/Core/_files b/Completion/Core/_files
index b6349a8c5..38eafd196 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -17,9 +17,12 @@ if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then
   # files and give up immediatly.
 
   opts=()
-  while getopts "P:S:W:F:J:V:X:f/g:" opt; do
-    [[ "$opt" = f ]] && return
-    [[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG")
+  while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do
+    case "$opt" in
+    f)            return;;
+    [PSrRWFJVXM]) opts=("$opts[@]" "-$opt" "$OPTARG");;
+    q)            opts=("$opts[@]" -q);;
+    esac
   done
 
   _path_files "$opts[@]" && ret=0
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 330eb9161..4496f5bda 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -24,6 +24,8 @@
 
 local comp ret=1 _compskip
 
+typeset -U _lastdescr
+
 setopt localoptions nullglob rcexpandparam
 unsetopt markdirs globsubst shwordsplit nounset ksharrays
 
@@ -56,6 +58,24 @@ for post in "$comppostfuncs[@]"; do
 done
 comppostfuncs=()
 
+_lastdescr=( "\`${(@)^_lastdescr:#}'" )
+if [[ compstate[nmatches] -eq 0 &&
+      -n "$compconfig[warning_format]" && $#_lastdescr -ne 0 ]]; then
+  local str
+
+  compstate[list]=list
+  compstate[force_list]=yes
+  compstate[insert]=''
+
+  case $#_lastdescr in
+  1) str="$_lastdescr[1]";;
+  2) str="$_lastdescr[1] or $_lastdescr[2]";;
+  *) str="${(j:, :)_lastdescr[1,-2]}, or $_lastdescr[-1]";;
+  esac
+
+  compadd -UX "${compconfig[warning_format]//\\%d/$str}" -n ''
+fi
+
 [[ "$compconfig[last_prompt]" = always ]] && compstate[last_prompt]=yes
 
 _lastcomp=( "${(@kv)compstate}" )
diff --git a/Completion/Core/_message b/Completion/Core/_message
index b7cb34ee1..ab1c67992 100644
--- a/Completion/Core/_message
+++ b/Completion/Core/_message
@@ -2,15 +2,14 @@
 
 local format
 
-format="$compconfig[message_format]"
-[[ -z "$format" ]] && format="$compconfig[description_format]"
+format="${compconfig[message_format]:-$compconfig[description_format]}"
 
 if [[ -n "$format" ]]; then
   if [[ $compstate[nmatches] -eq 0 ]]; then
     compstate[list]=list
+    compstate[force_list]=yes
     compstate[insert]=''
     compadd -UX "${format//\\%d/$1}" -n ''
-    compstate[force_list]=yes
   else
     compadd -X "${format//\\%d/$1}" -n '' && compstate[force_list]=yes
   fi
diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts
index 30a68d312..e842db754 100644
--- a/Completion/Core/_multi_parts
+++ b/Completion/Core/_multi_parts
@@ -8,16 +8,24 @@
 # separator character are then completed independently.
 
 local sep matches pref npref i tmp1 group expl menu pre suf opre osuf cpre
+local opts sopts match
 typeset -U tmp2
 
 # Get the options.
 
 group=()
 expl=()
-while getopts "J:V:X:" opt; do
+opts=()
+sopts=()
+while getopts "J:V:X:P:S:r:R:qM:" opt; do
   case "$opt" in
-  [JV]) group=("-$opt" "$OPTARG");;
-  X)    expl=(-X "$OPTARG");;
+  [JV])  group=("-$opt" "$OPTARG");;
+  X)     expl=(-X "$OPTARG");;
+  P)     opts=( "$opts[@]" -P "$OPTARG")
+         sopts=( "$sopts[@]" -P "$OPTARG");;
+  [SrR]) sopts=( "$sopts[@]" -P "$OPTARG");;
+  q)     sopts=( "$sopts[@]" -q);;
+  M)     match="$OPTARG";;
   esac
 done
 shift OPTIND-1
@@ -57,7 +65,7 @@ pref=''
 # If the string from the line matches at least one of the strings,
 # we use only the matching strings.
 
-compadd -O tmp1 -M "r:|${sep}=* r:|=*" - "$matches[@]"
+compadd -O tmp1 -M "r:|${sep}=* r:|=* $match" - "$matches[@]"
 
 (( $#tmp1 )) && matches=( "$tmp1[@]" )
 
@@ -106,11 +114,11 @@ while true; do
 	SUFFIX="$suf"
 
 	if (( $#tmp2 )); then
-	  compadd "$group[@]" "$expl[@]" -p "$pref" -qS "$sep" \
-                  -M "r:|${sep}=* r:|=*" - "$tmp1[1]"
+	  compadd "$group[@]" "$expl[@]" -p "$pref" -qS "$sep" "$opts[@]" \
+                  -M "r:|${sep}=* r:|=* $match" - "$tmp1[1]"
         else
-	  compadd "$group[@]" "$expl[@]" -p "$pref" \
-                  -M "r:|${sep}=* r:|=*" - "$tmp1[1]"
+	  compadd "$group[@]" "$expl[@]" -p "$pref" "$sopts[@]" \
+                  -M "r:|${sep}=* r:|=* $match" - "$tmp1[1]"
         fi
 	return 0
       fi
@@ -121,7 +129,7 @@ while true; do
 
       PREFIX="$pre"
       SUFFIX="$suf"
-      compadd -O matches -M "r:|${sep}=* r:|=*" - "$matches[@]"
+      compadd -O matches -M "r:|${sep}=* r:|=* $match" - "$matches[@]"
 
       if [[ "$pre" = *${sep}* ]]; then
  	PREFIX="${cpre}${pre%%${sep}*}"
@@ -138,12 +146,12 @@ while true; do
 
         tmp2="$pre$suf"
         if [[ "$tmp2" = *${sep}* ]]; then
-          compadd "$group[@]" "$expl[@]" \
+          compadd "$group[@]" "$expl[@]" "$sopts[@]" \
                   -p "$pref" -s "${sep}${tmp2#*${sep}}" \
-                  -M "r:|${sep}=* r:|=*" - "$tmp1[@]"
+                  -M "r:|${sep}=* r:|=* $match" - "$tmp1[@]"
         else
-          compadd "$group[@]" "$expl[@]" -p "$pref"\
-                  -M "r:|${sep}=* r:|=*" - "$tmp1[@]"
+          compadd "$group[@]" "$expl[@]" -p "$pref" "$sopts[@]" \
+                  -M "r:|${sep}=* r:|=* $match" - "$tmp1[@]"
         fi
       else
         # With normal completion we add all matches one-by-one with
@@ -152,12 +160,12 @@ while true; do
 
         for i in "${(@M)matches:#(${(j:|:)~tmp1})*}"; do
 	  if [[ "$i" = *${sep}* ]]; then
-            compadd "$group[@]" "$expl[@]" -S '' \
+            compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
 	            -p "$pref" -s "${i#*${sep}}" \
-                    -M "r:|${sep}=* r:|=*" - "${i%%${sep}*}${sep}"
+                    -M "r:|${sep}=* r:|=* $match" - "${i%%${sep}*}${sep}"
           else
-            compadd "$group[@]" "$expl[@]" -S '' -p "$pref" \
-                    -M "r:|${sep}=* r:|=*" - "$i"
+            compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" -p "$pref" \
+                    -M "r:|${sep}=* r:|=* $match" - "$i"
           fi
         done
       fi
@@ -173,11 +181,11 @@ while true; do
       SUFFIX="$suf"
 
       if [[ -n "$suf" ]]; then
-        compadd "$group[@]" "$expl[@]" -s "$suf" \
-                -M "r:|${sep}=* r:|=*" - "$pref$pre"
+        compadd "$group[@]" "$expl[@]" -s "$suf" "$sopts[@]" \
+                -M "r:|${sep}=* r:|=* $match" - "$pref$pre"
       else
-        compadd "$group[@]" "$expl[@]" -S '' \
-                -M "r:|${sep}=* r:|=*" - "$pref$pre"
+        compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
+                -M "r:|${sep}=* r:|=* $match" - "$pref$pre"
       fi
       return 0
     fi
@@ -208,7 +216,8 @@ while true; do
     SUFFIX=""
 
     [[ -n "$pref" && "$orig" != "$pref" ]] &&
-        compadd "$group[@]" "$expl[@]" -S '' -M "r:|${sep}=* r:|=*" - "$pref"
+        compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
+                -M "r:|${sep}=* r:|=* $match" - "$pref"
 
     return
   fi
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 455de444d..eb9c06da6 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -6,7 +6,7 @@
 local linepath realpath donepath prepath testpath exppath
 local tmp1 tmp2 tmp3 tmp4 i orig pre suf tpre tsuf opre osuf cpre
 local pats haspats=no ignore group expl addpfx addsfx remsfx
-local nm=$compstate[nmatches] menu
+local nm=$compstate[nmatches] menu match matcher
 
 typeset -U prepaths exppaths
 
@@ -23,10 +23,11 @@ addpfx=()
 addsfx=()
 remsfx=()
 expl=()
+matcher=()
 
 # Get the options.
 
-while getopts "P:S:qr:R:W:F:J:V:X:f/g:" opt; do
+while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:" opt; do
   case "$opt" in
   P)     addpfx=(-P "$OPTARG")
          ;;
@@ -68,6 +69,9 @@ while getopts "P:S:qr:R:W:F:J:V:X:f/g:" opt; do
          pats=("$pats[@]" ${=OPTARG})
 	 haspats=yes
 	 ;;
+  M)     match="$OPTARG"
+         matcher=(-M "$OPTARG")
+         ;;
   esac
 done
 
@@ -124,9 +128,11 @@ if [[ -z "$suf" && $#ignore -eq 0 && $#remsfx -eq 0 &&
   # Now call compgen.
 
   if [[ -z "$gopt" ]]; then
-    compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt
+    compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
+            "$tmp1[@]" "$matcher[@]" $sopt
   else
-    compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats"
+    compgen "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
+            "$tmp1[@]" "$matcher[@]" $sopt -g "$pats"
   fi
 
   # If this generated any matches, we don't want to do in-path completion.
@@ -243,7 +249,7 @@ for prepath in "$prepaths[@]"; do
       # See which of them match what's on the line.
 
       tmp2=("$tmp1[@]")
-      compadd -D tmp1 "$ignore[@]" - "${(@)tmp1:t}"
+      compadd -D tmp1 "$ignore[@]" "$matcher[@]" - "${(@)tmp1:t}"
 
       # If no file matches, save the expanded path and continue with
       # the outer loop.
@@ -346,14 +352,14 @@ for prepath in "$prepaths[@]"; do
         if [[ "$tmp3" = */* ]]; then
 	  compadd -Qf -p "$linepath${testpath:q}" -s "/${tmp3#*/}" \
 	          -W "$prepath$realpath$testpath" "$ignore[@]" \
-		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
-		  "$group[@]" "$expl[@]" \
+		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
+                  -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
 		  - "${(@)${(@)tmp1%%/*}:q}"
 	else
 	  compadd -Qf -p "$linepath${testpath:q}" \
 	          -W "$prepath$realpath$testpath" "$ignore[@]" \
-		   "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
-		   "$group[@]" "$expl[@]" \
+		   "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
+                   -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
 		   - "${(@)tmp1:q}"
 	fi
       else
@@ -361,15 +367,15 @@ for prepath in "$prepaths[@]"; do
           for i in "$tmp1[@]"; do
 	    compadd -Qf -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
 		    -W "$prepath$realpath$testpath" "$ignore[@]" \
-		    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
-		    "$group[@]" "$expl[@]" \
+		    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
+                    -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
 		    - "${${i%%/*}:q}"
 	  done
         else
 	  compadd -Qf -p "$linepath${testpath:q}" \
 		  -W "$prepath$realpath$testpath" "$ignore[@]" \
-		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
-		  "$group[@]" "$expl[@]" \
+		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
+                  -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
 		  - "${(@)tmp1:q}"
         fi
       fi
@@ -400,8 +406,8 @@ for prepath in "$prepaths[@]"; do
     SUFFIX=""
     compadd -Qf -p "$linepath${testpath:q}" \
 	    -W "$prepath$realpath$testpath" "$ignore[@]" \
-	    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
-	    "$group[@]" "$expl[@]" \
+	    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
+            -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
 	    - "${(@)tmp1:q}"
   fi
 done
@@ -417,7 +423,7 @@ if [[ -n "$compconfig[path_expand]" &&
   PREFIX="${opre}${osuf}"
   SUFFIX=""
   compadd -Q -S '' "$group[@]" "$expl[@]" \
-          -M 'r:|/=* r:|=*' -p "$linepath" - "$exppaths[@]"
+          -M "r:|/=* r:|=* $match" -p "$linepath" - "$exppaths[@]"
 fi
 
 [[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts
index 0a8cae28f..c65a944e3 100644
--- a/Completion/Core/_sep_parts
+++ b/Completion/Core/_sep_parts
@@ -18,16 +18,20 @@
 # `-X explanation' options.
 
 local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
-local matchflags opt group expl nm=$compstate[nmatches] opre osuf
+local matchflags opt group expl nm=$compstate[nmatches] opre osuf opts match
 
 # Get the options.
 
 group=()
 expl=()
-while getopts "J:V:X:" opt; do
+opts=()
+while getopts "J:V:X:P:S:r:R:qM:" opt; do
   case "$opt" in
   [JV]) group=("-$opt" "$OPTARG");;
   X)    expl=(-X "$OPTARG");;
+  q)    opts=( "$opts[@]" -q );;
+  M)    match="$OPTARG";;
+  *)    opts=( "$opts[@]" "-$opt" "$OPTARG" );;
   esac
 done
 shift OPTIND-1
@@ -142,14 +146,14 @@ done
 # If we have collected matching specifications, we build an array
 # from it that can be used as arguments to `compadd'.
 
-[[ $#matchers -gt 0 ]] && matchers=(-M "$matchers")
+[[ $#matchers+$#match -gt 0 ]] && matchers=(-M "$matchers $match")
 
 # Add the matches for each of the suffixes.
 
 PREFIX="$pre"
 SUFFIX="$suf"
 for i in "$suffixes[@]"; do
-  compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \
+  compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" "$opts[@]" \
           -i "$IPREFIX" -I "$ISUFFIX" -p "$prefix" -s "$i" - "$testarr[@]"
 done
 
diff --git a/Doc/Zsh/compctl.yo b/Doc/Zsh/compctl.yo
index 03a47f9c4..6b017cedc 100644
--- a/Doc/Zsh/compctl.yo
+++ b/Doc/Zsh/compctl.yo
@@ -132,7 +132,8 @@ the default.  In other words, completion will subsequently use the
 options specified by the tt(-D) flag.
 
 The form with tt(-M) as the first and only option defines global
-matching specifications, as described below in noderef(Matching Control).
+matching specifications, as described below in noderef(Matching
+Control).
 
 texinode(Option Flags)(Alternative Completion)(Command Flags)(Programmable Completion Using compctl)
 sect(Option Flags)
@@ -820,7 +821,9 @@ option applies only to a particular command.  In this case, when
 completion is attempted for any command, the code will try the
 specifications in order until one matches.  This allows one to define
 simple and fast matches to be used first, more powerful matchers as a
-second choice, and so on.
+second choice, and so on. These global matchers can also be defined by 
+setting the tt(compmatchers) special array to the strings that would
+otherwise be given to tt(compctl -M) as arguments.
 
 For example, one can make the code match trial completions that contain
 the string on the command line as a substring, not just at the
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 370585863..d66df069d 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -13,14 +13,18 @@ completion behaviour and which may be bound to keystrokes, are referred to
 as `widgets'.
 
 Note that with the function-based completions described here, it
-is also possible to use the `tt(compctl -M ...)' mechanism to specify
+is also possible to use the `tt(compctl -M ...)' mechanism and the
+tt(compmatchers) special array to specify
 global matching control, such as case-insensitivity (`tt(abc)' will complete
 to a string beginning `tt(ABC)'), or wildcard behaviour on
 certain anchors (`tt(a-d)' will complete to abc-def as if there were a
 `tt(*)' after the `a').  See
 ifzman(the section `Matching Control' in zmanref(zshcompctl))\
 ifnzman(noderef(Matching Control))
-for further details.
+for further details. Note that it is recommended to use the the
+tt(compmatchers) array instead of tt(compctl) to define global
+matchers when using the function based completion system, although
+using tt(compctl -M) still works.
 
 startmenu()
 menu(Initialization)
@@ -674,8 +678,8 @@ names in the way normal filenames are completed by the
 tt(_path_files) function.
 
 Like other utility functions, this function accepts the `tt(-V)',
-`tt(-J)', and `tt(-X)' options with an argument and passes them to the
-tt(compadd) builtin.
+`tt(-J)', `tt(-X)', `tt(-M)', `tt(-P)', `tt(-S)', `tt(-r)', `tt(-R)', and
+`tt(-q)' options and passes them to the tt(compadd) builtin.
 )
 item(tt(_sep_parts))(
 This function gets as arguments alternating arrays and separators.
@@ -686,8 +690,9 @@ a quoted list of words in parentheses. For example, with the array
 complete the string  `tt(f)' to `tt(foo)' and the string `tt(b@n)' to
 `tt(bar@news)'.
 
-This function passes the `tt(-V)', `tt(-J)', and `tt(-X)' options and
-their arguments to the tt(compadd) builtin used to add the matches.
+This function passes the `tt(-V)', `tt(-J)', `tt(-X)', `tt(-M)', `tt(-P)',
+`tt(-S)', `tt(-r)', `tt(-R)', and `tt(-q)' options and their arguments
+to the tt(compadd) builtin used to add the matches.
 )
 item(tt(_path_files) and tt(_files))(
 The function tt(_path_files) is used throughout the shell code
@@ -705,9 +710,9 @@ The function tt(_files) calls tt(_path_files) with all the arguments
 it was passed and, if that generated no matches, calls tt(_path_files) again
 without any tt(-g) or tt(-/) option, thus generating all filenames.
 
-These functions also accept the `tt(-J)', `tt(-V)', `tt(-X)', `tt(-P)',
-`tt(-S)', `tt(-q)', `tt(-r)', and `tt(-R)' options from the
-tt(compadd) builtin.
+These functions also accept the `tt(-J)', `tt(-V)', `tt(-X)',
+`tt(-M)', `tt(-P)', `tt(-S)', `tt(-q)', `tt(-r)', and `tt(-R)' options
+from the tt(compadd) builtin.
 
 Finally, the tt(_path_files) function supports two configuration keys.
 startitem()
@@ -865,7 +870,16 @@ the global parameter tt(state) and the function returns with a return
 value of 300 (to make it distinguishable from other return values)
 after setting the global `tt(line)' and `tt(opt_args)'
 parameters as described below and without resetting any changes made
-to the special parameters such as tt(PREFIX) and tt(words).
+to the special parameters such as tt(PREFIX) and tt(words). Note that
+this means that a function calling tt(_arguments) with at least one
+action containing such a `tt(->)var(string)' has to declare
+appropriate local parameters as in:
+
+example(local state line
+typeset -A opt_args)
+
+This will ensure that tt(_arguments) does not create unused global
+parameters.
 
 A string in
 braces will be evaluated to generate the matches and if the
@@ -1047,7 +1061,14 @@ tt(describe_options) is used by the tt(_arguments) function.
 
 One last difference is that this function uses the associative array
 tt(val_args) to report values and their arguments (but otherwise this
-is the same as the tt(opt_args) association used by tt(_arguments)).
+is the same as the tt(opt_args) association used by
+tt(_arguments)). This also means that the function calling tt(_values) 
+should declare the tt(state) and tt(val_args) parameters as in:
+
+example(local state line
+typeset -A val_args)
+
+when using an action of the form `tt(->)var(string)'.
 )
 item(tt(_regex_arguments))(
 This function is a compiler to generate a completion function.  The
@@ -1387,6 +1408,12 @@ item(tt(message_format))(
 Like tt(description_format), but used when displaying messages in
 those places where no completions can automatically be generated.
 )
+item(tt(warning_format))(
+Like the previous two, but used by tt(_main_complete) to show a
+warning if no matches could be generated. Any `tt(%d)' sequence in the 
+value will be replaced by the descriptions for the matches that were
+expected.
+)
 item(tt(option_prefix))(
 If set to a non-empty value, options will only be generated as
 possible matches when no other completions could be found or if the
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 1b72fa923..d09fff259 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -122,6 +122,33 @@ cpcpattern(Cpattern o)
     return r;
 }
 
+/* Set the global match specs. */
+
+/**/
+static int
+set_gmatcher(char *name, char **argv)
+{
+    Cmlist l = NULL, *q = &l, n;
+    Cmatcher m;
+
+    while (*argv) {
+	if ((m = parse_cmatcher(name, *argv)) == pcm_err)
+	    return 1;
+	*q = n = (Cmlist) zhalloc(sizeof(struct cmlist));
+	n->next = NULL;
+	n->matcher = m;
+	n->str = *argv++;
+
+	q = &(n->next);
+    }
+    freecmlist(cmatcher);
+    PERMALLOC {
+	cmatcher = cpcmlist(l);
+    } LASTALLOC;
+
+    return 1;
+}
+
 /* Try to get the global matcher from the given compctl. */
 
 /**/
@@ -130,27 +157,13 @@ get_gmatcher(char *name, char **argv)
 {
     if (!strcmp(*argv, "-M")) {
 	char **p = ++argv;
-	Cmlist l = NULL, *q = &l, n;
-	Cmatcher m;
 
 	while (*p) {
 	    if (**p++ == '-')
 		return 0;
 	}
-	while (*argv) {
-	    if ((m = parse_cmatcher(name, *argv)) == pcm_err)
-		return 2;
-	    *q = n = (Cmlist) zhalloc(sizeof(struct cmlist));
-	    n->next = NULL;
-	    n->matcher = m;
-	    n->str = *argv++;
-
-	    q = &(n->next);
-	}
-	freecmlist(cmatcher);
-	PERMALLOC {
-	    cmatcher = cpcmlist(l);
-	} LASTALLOC;
+	if (set_gmatcher(name, argv))
+	    return 2;
 
 	return 1;
     }
@@ -2586,6 +2599,42 @@ cond_range(char **a, int id)
 			(id ? cond_str(a, 1, 1) : NULL), 0);
 }
 
+/**/
+static void
+cmsetfn(Param pm, char **v)
+{
+    set_gmatcher(pm->nam, v);
+}
+
+/**/
+static char **
+cmgetfn(Param pm)
+{
+    int num;
+    Cmlist p;
+    char **ret, **q;
+
+    for (num = 0, p = cmatcher; p; p = p->next, num++);
+
+    ret = (char **) zhalloc((num + 1) * sizeof(char *));
+
+    for (q = ret, p = cmatcher; p; p = p->next, q++)
+	*q = dupstring(p->str);
+    *q = NULL;
+
+    return ret;
+}
+
+/**/
+static void
+cmunsetfn(Param pm, int exp)
+{
+    char *dummy[1];
+
+    dummy[0] = NULL;
+    set_gmatcher(pm->nam, dummy);
+}
+
 static struct builtin bintab[] = {
     BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
     BUILTIN("compgen", 0, bin_compgen, 1, -1, 0, NULL, NULL),
@@ -2605,6 +2654,10 @@ static struct funcwrap wrapper[] = {
     WRAPDEF(comp_wrapper),
 };
 
+static struct paramdef patab[] = {
+    PARAMDEF("compmatchers", PM_ARRAY|PM_SPECIAL, NULL, cmsetfn, cmgetfn, cmunsetfn)
+};
+
 /**/
 int
 setup_compctl(Module m)
@@ -2621,6 +2674,7 @@ boot_compctl(Module m)
 {
     if(!(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
 	 addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
+	 addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)) |
 	 !addwrapper(m, wrapper)))
 	return 1;
     return 0;
@@ -2634,6 +2688,7 @@ cleanup_compctl(Module m)
 {
     deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
     deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
+    deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
     deletewrapper(m, wrapper);
     return 0;
 }
diff --git a/Src/Zle/compctl.mdd b/Src/Zle/compctl.mdd
index e7b2cfb68..c52285c72 100644
--- a/Src/Zle/compctl.mdd
+++ b/Src/Zle/compctl.mdd
@@ -4,4 +4,6 @@ autobins="compctl compgen compadd compset"
 
 autoprefixconds="prefix suffix between after"
 
+autoparams="compmatchers"
+
 objects="compctl.o"