about summary refs log tree commit diff
path: root/Completion/Core
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:24:09 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:24:09 +0000
commit6c1fb551ba0973c9a86e1ea479d553d66c6bf6b7 (patch)
treeec80a986c49f2da21eed83b7097f0f4e99f57e3f /Completion/Core
parent640a840d2e94f0fc245ef8632050c37af23c6b94 (diff)
downloadzsh-6c1fb551ba0973c9a86e1ea479d553d66c6bf6b7.tar.gz
zsh-6c1fb551ba0973c9a86e1ea479d553d66c6bf6b7.tar.xz
zsh-6c1fb551ba0973c9a86e1ea479d553d66c6bf6b7.zip
zsh-3.1.5-pws-14 zsh-3.1.5-pws-14
Diffstat (limited to 'Completion/Core')
-rw-r--r--Completion/Core/.distfiles5
-rw-r--r--Completion/Core/_approximate197
-rw-r--r--Completion/Core/_complete52
-rw-r--r--Completion/Core/_correct19
-rw-r--r--Completion/Core/_expand149
-rw-r--r--Completion/Core/_list61
-rw-r--r--Completion/Core/_main_complete249
-rw-r--r--Completion/Core/_match53
-rw-r--r--Completion/Core/_multi_parts25
-rw-r--r--Completion/Core/_options5
-rw-r--r--Completion/Core/_parameters8
-rw-r--r--Completion/Core/_path_files84
-rw-r--r--Completion/Core/_sep_parts7
-rw-r--r--Completion/Core/_set_options7
-rw-r--r--Completion/Core/_unset_options7
-rw-r--r--Completion/Core/compdump2
-rw-r--r--Completion/Core/compinit13
17 files changed, 696 insertions, 247 deletions
diff --git a/Completion/Core/.distfiles b/Completion/Core/.distfiles
index ddf2a707e..6babe9701 100644
--- a/Completion/Core/.distfiles
+++ b/Completion/Core/.distfiles
@@ -1,5 +1,6 @@
 DISTFILES_SRC='
     .distfiles
-    _compalso _files _main_complete _multi_parts _normal _path_files
-    _sep_parts compdump compinit
+    _approximate _compalso _complete _correct _expand _files _list
+    _main_complete _match _multi_parts _normal _options _parameters
+    _path_files _sep_parts _set_options _unset_options compdump compinit
 '
diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate
new file mode 100644
index 000000000..1b40f7cbf
--- /dev/null
+++ b/Completion/Core/_approximate
@@ -0,0 +1,197 @@
+#autoload
+
+# This code will try to correct the string on the line based on the
+# strings generated for the context if `compconfig[correct]' is set.
+# These corrected strings will be shown in a list and one can
+# cycle through them as in a menucompletion or get the corrected prefix.
+#
+# Supported configuration keys:
+#
+#  approximate_accept
+#    This should be set to a number, specifying the maximum number
+#    of errors that should be accepted. If the string also contains
+#    a `n' or `N', the code will use the numeric argument as the
+#    maximum number of errors if a numeric argument was given. If no
+#    numeric argument was given, the number from the value of this
+#    key will be used. E.g. with `compconf approximate_accept=2n' two
+#    errors will be accepted, but if the user gives another number
+#    with the numeric argument, this will be prefered. Also, with
+#    `compconf approximate_accept=0n', normally no correction will be
+#    tried, but if a numeric argument is given, automatic correction
+#    will be used. On the other hand, if the string contains an `!'
+#    and a `n' or `N', correction is not attempted if a numeric
+#    argument is given. Once the number of errors to accept is
+#    determined, the code will repeatedly try to generate matches by
+#    allowing one error, two errors, and so on. Independent of the
+#    number of errors the user wants to accept, the code will allow
+#    only fewer errors than there are characters in the string from
+#    the line.
+#
+#  approximate_original
+#    This value is used to determine if the original string should
+#    be included in the list (and thus be presented to the user when
+#    cycling through the corrections). If it is set to any non-empty
+#    value, the original string will be offered. If it contains the
+#    sub-string `last', the original string will appear as the last
+#    string when cycling through the corrections, otherwise it will
+#    appear as the first one (so that the command line does not
+#    change immediately). Also, if the value contains the sub-string
+#    `always', the original string will always be included, whereas
+#    normally it is included only if more than one possible
+#    correction was generated.
+#
+#  approximate_prompt
+#    This can be set to a string that should be printed before the
+#    list of corrected strings when cycling through them. This string
+#    may contain the control sequences `%n', `%B', etc. known from
+#    the `-X' option of `compctl'. Also, the sequence `%e' will be
+#    replaced by the number of errors accepted to generate the
+#    corrected strings.
+#
+#  approximate_insert
+#    If this is set to a string starting with `unambig', the code
+#    will try to insert a usable unambiguous string in the command
+#    line instead of always cycling through the corrected strings.
+#    If such a unambiguous string could be found, the original
+#    string is not used, independent of the setting of
+#    `approximate_original'. If no sensible string could be found,
+#    one can cycle through the corrected strings as usual.
+#
+# If any of these keys is not set, but the the same key with the
+# prefix `correct' instead of `approximate' is set, that value will
+# be used.
+
+local _comp_correct _correct_prompt comax
+local cfgacc cfgorig cfgps cfgins
+
+# Only if all global matchers hav been tried.
+
+[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
+
+# We don't try correction if the string is too short.
+
+[[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
+
+# Get the configuration values, using either the prefix `correct' or
+# `approximate'.
+
+if [[ "$compstate[pattern_match]" = (|\**) ]]; then
+  cfgacc="${compconfig[approximate_accept]:-$compconfig[correct_accept]}"
+  cfgorig="${compconfig[approximate_original]:-$compconfig[correct_original]}"
+  cfgps="${compconfig[approximate_prompt]:-$compconfig[correct_prompt]}"
+  cfgins="${compconfig[approximate_insert]:-$compconfig[correct_insert]}"
+else
+  cfgacc="$compconfig[correct_accept]"
+  cfgorig="$compconfig[correct_original]"
+  cfgps="$compconfig[correct_prompt]"
+  cfgins="$compconfig[correct_insert]"
+fi
+
+# Get the number of errors to accept.
+
+if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then
+  # Stop if we also have a `!'.
+
+  [[ "$cfgacc" = *\!* ]] && return 1
+
+  # Prefer the numeric argument if that has a sensible value.
+
+  comax="$NUMERIC"
+else
+  comax="${cfgacc//[^0-9]}"
+fi
+
+# If the number of errors to accept is too small, give up.
+
+[[ "$comax" -lt 1 ]] && return 1
+
+# Otherwise temporarily define functions to use instead of
+# the builtins that add matches. This is used to be able
+# to stick the `(#a...)' into the right place (after an
+# ignored prefix).
+
+compadd() {
+  [[ "$*" != *-([a-zA-Z/]#|)U* &&
+     "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
+
+  if [[ "$PREFIX" = \~*/* ]]; then
+    PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+  else
+    PREFIX="(#a${_comp_correct})$PREFIX"
+  fi
+  if [[ -n "$_correct_prompt" ]]; then
+    builtin compadd -X "$_correct_prompt" -J _correct "$@"
+  else
+    builtin compadd -J _correct "$@"
+  fi
+}
+
+compgen() {
+  [[ "$*" != *-([a-zA-Z/]#|)U* &&
+     "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
+
+  if [[ "$PREFIX" = \~*/* ]]; then
+    PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+  else
+    PREFIX="(#a${_comp_correct})$PREFIX"
+  fi
+  if [[ -n "$_correct_prompt" ]]; then
+    builtin compgen "$@" -X "$_correct_prompt" -J _correct
+  else
+    builtin compgen "$@" -J _correct
+  fi
+}
+
+# Now initialise our counter. We also set `compstate[matcher]'
+# to `-1'. This allows completion functions to use the simple
+# `[[ compstate[matcher] -gt 1 ]] && return' to avoid being
+# called for multiple global match specs and still be called 
+# again when correction is done. Also, this makes it easy to
+# test if correction is attempted since `compstate[matcher]'
+# will never be set to a negative value by the completion code.
+
+_comp_correct=1
+compstate[matcher]=-1
+
+_correct_prompt="${cfgps//\%e/1}"
+
+# We also need to set `extendedglob' and make the completion
+# code behave as if globcomplete were set.
+
+setopt extendedglob
+
+[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*'
+
+while [[ _comp_correct -le comax ]]; do
+  if _complete; then
+    if [[ "$cfgins" = unambig* &&
+          "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
+      compstate[pattern_insert]=unambiguous
+    elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then
+      if [[ "$cfgorig" = *last* ]]; then
+        builtin compadd -U -V _correct_original -nQ - "$PREFIX$SUFFIX"
+      elif [[ -n "$cfgorig" ]]; then
+	builtin compadd -U -nQ - "$PREFIX$SUFFIX"
+      fi
+
+      # If you always want to see the list of possible corrections,
+      # set `compstate[list]=list' here.
+
+      compstate[force_list]=list
+    fi
+    compstate[matcher]="$compstate[total_matchers]"
+    unfunction compadd compgen
+
+    return 0
+  fi
+
+  [[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
+  (( _comp_correct++ ))
+
+  _correct_prompt="${cfgps//\%e/$_comp_correct}"
+done
+
+compstate[matcher]="$compstate[total_matchers]"
+unfunction compadd compgen
+
+return 1
diff --git a/Completion/Core/_complete b/Completion/Core/_complete
new file mode 100644
index 000000000..0f4d5ff4b
--- /dev/null
+++ b/Completion/Core/_complete
@@ -0,0 +1,52 @@
+#autoload
+
+# Generate all possible completions. Note that this is not intended as
+# a normal completion function, but as one possible value for the
+# compconfig[completer] parameter.
+
+local comp name
+
+# An entry for `-first-' is the replacement for `compctl -T'
+# Completion functions may set `_compskip' to any value to make the 
+# main loops stop calling other completion functions.
+
+comp="$_comps[-first-]"
+if [[ ! -z "$comp" ]]; then
+  "$comp"
+  if (( $+_compskip )); then
+    unset _compskip
+    (( compstate[nmatches] ))
+    return
+  fi
+fi
+
+# For arguments and command names we use the `_normal' function.
+
+if [[ "$compstate[context]" = command ]]; then
+  _normal
+else
+  # Let's see if we have a special completion definition for the other
+  # possible contexts.
+
+  comp=''
+
+  case $compstate[context] in
+  equal)           comp="$_comps[-equal-]";;
+  tilde)           comp="$_comps[-tilde-]";;
+  redirect)        comp="$_comps[-redirect-]";;
+  math)            comp="$_comps[-math-]";;
+  subscript)       comp="$_comps[-subscript-]";;
+  value)           comp="$_comps[-value-]";;
+  array_value)     comp="$_comps[-array-value-]";;
+  condition)       comp="$_comps[-condition-]";;
+  parameter)       comp="$_comps[-parameter-]";;
+  brace_parameter) comp="$_comps[-brace-parameter-]";;
+  esac
+
+  # If not, we use default completion, if any.
+
+  [[ -z "$comp" ]] && comp="$_comps[-default-]"
+  [[ -z "$comp" ]] || "$comp"
+fi
+
+(( compstate[nmatches] ))
diff --git a/Completion/Core/_correct b/Completion/Core/_correct
new file mode 100644
index 000000000..35ab01cf1
--- /dev/null
+++ b/Completion/Core/_correct
@@ -0,0 +1,19 @@
+#autoload
+
+# This is mainly a wrapper around the more general `_approximate.
+# By setting `compstate[pattern_match]' to something unequal to `*' and
+# then calling `_approximate, we get only corrections, not all strings
+# with the corrected prefix and something after it.
+#
+# Supported configuration keys are the same as for `_approximate', only
+# starting with `correct'.
+
+local ret=1 opm="$compstate[pattern_match]"
+
+compstate[pattern_match]='-'
+
+_approximate && ret=0
+
+compstate[pattern_match]="$opm"
+
+return ret
diff --git a/Completion/Core/_expand b/Completion/Core/_expand
new file mode 100644
index 000000000..9172b6cbf
--- /dev/null
+++ b/Completion/Core/_expand
@@ -0,0 +1,149 @@
+#autoload
+
+# This completer function is intended to be used as the first completer
+# function and allows one to say more explicitly when and how the word
+# from the line should be expanded than expand-or-complete.
+# This function will allow other completer functions to be called if
+# the expansions done produce no result or do not change the original
+# word from the line.
+#
+# Configuration keys:
+#
+#  expand_substitute
+#    If this is unset or set to the empty string, the code will first
+#    try to expand all substitutions in the string (such as $(...) and
+#    ${...}). If this is set to an non-empty string it should be 
+#    an expression usable inside a $[...] arithmetical expression.
+#    In this case, expansion of substitutions will be done if the
+#    expression evaluates to `1'. For example, with
+#
+#      compconf expand_substitute='NUMERIC != 1'
+#
+#    substitution will be performed only if given an explicit numeric
+#    argument other than `1', as by typing ESC 2 TAB.
+#
+#  expand_glob
+#    If this is unset or set to an empty string, globbing will be
+#    attempted on the word resulting from substitution or the
+#    original string. The values accepted for this key are the same
+#    as for expand_substitute.
+#
+#  expand_menu
+#    If this is unset or set to the empty string, the words resulting
+#    from expansion (if any) will simply be inserted in the ommand line,
+#    replacing the original string. However, if this key is set to an
+#    non-empty string, the user can cycle through the expansion as in
+#    a menucompletion. Unless the value contains the sub-string `only',
+#    the user will still be offered all expansions at once as one of
+#    the strings to insert in the command line. Also, if the value
+#    contains the sub-string `last', the string with all expansion will
+#    be offered first, whereas normally it is offered as the last string
+#    to insert. Finally, if the value contains the sub-string `sort',
+#    the expansions will be sorted alphabetically, normally they are
+#    kept in the order the expansion produced them in.
+#    
+#  expand_original
+#    If this is set to an non-empty string, the original string from the
+#    line will be included in the list of strings the user can cycle
+#    through as in a menucompletion. If the value contains the sub-string
+#    `last', the original string will appear as the last string, with
+#    other values it is inserted as the first one (so that the command
+#    line does not change immediatly).
+#
+#  expand_prompt
+#    This may be set to a string that should be displayed before the
+#    possible expansions. This is given to the -X option and thus may
+#    contain the control sequences `%n', `%B', etc. Also, the sequence
+#    `%o' in this string will be replaced by the original string.
+
+local exp word="$PREFIX$SUFFIX" group=-V
+
+# Do this only for the first global matcher.
+
+[[ "$compstate[matcher]" -le 1 ]] || return 1
+
+# In exp we will collect the expansion.
+
+exp=("$word")
+
+# First try substitution. That weird thing spanning multiple lines
+# changes quoted spaces, tabs, and newlines into spaces.
+
+[[ -z "$compconfig[expand_substitute]" ||
+   "${(e):-\$[$compconfig[expand_substitute]]}" -eq 1 ]] &&
+    exp=( "${(e)exp//\\[ 	
+]/ }" )
+
+# If the array is empty, store the original string again.
+
+[[ -z "$exp" ]] && exp=("$word")
+
+# Now try globbing.
+
+[[ -z "$compconfig[expand_glob]" ||
+   "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] &&
+    exp=( ${~exp}(N) )
+
+# If we don't have any expansions or only one and that is the same
+# as the original string, we let other completers run.
+
+[[ $#exp -eq 0 ||
+   ( $#exp -eq 1 && "$exp[1]" = "$word" ) ]] && return 1
+
+# We have expansions, should we menucomplete them?
+
+if [[ -z "$compconfig[expand_menu]" ]]; then
+
+  # No, so if the user only wants a list, we add the strings
+  # separately. Otherwise we add the whole array as one string,
+  # probably also adding the original string.
+
+  if [[ -z "$compstate[insert]" ]]; then
+    compadd -U -V _expand -Q - "$exp[@]"
+  else
+    [[ -n "$compconfig[expand_original]" && 
+       "$compconfig[expand_original]" != *last* ]] &&
+        compadd -UnQ -V _expand_original - "$word"
+
+    compadd -UQ -V _expand - "$exp"
+
+    [[ -n "$compconfig[expand_original]" && 
+       "$compconfig[expand_original]" = *last* ]] &&
+        compadd -UnQ -V _expand_original - "$word"
+
+    compstate[insert]=menu
+  fi
+else
+  # Sorting? We just use a different group type then.
+
+  [[ "$compconfig[expand_menu]" = *sort* ]] && group=-J
+
+  # Now add the expansion string, probably also adding the original
+  # and/or the string containing all expanded string.
+
+  [[ -n "$compconfig[expand_original]" && 
+     "$compconfig[expand_original]" != *last* ]] &&
+      compadd -UnQ -V _expand_original - "$word"
+
+  [[ "$compconfig[expand_menu]" = *last* &&
+     "$compconfig[expand_menu]" != *only* ]] &&
+      compadd -UnQ -V _expand_all - "$exp"
+
+  if [[ -z "$compconfig[expand_prompt]" ]]; then
+    compadd -UQ $group _expand - "$exp[@]"
+  else
+    compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \
+            $group _expand - "$exp[@]"
+  fi
+  [[ "$compconfig[expand_menu]" != *last* &&
+     "$compconfig[expand_menu]" != *only* ]] &&
+      compadd -UnQ -V _expand_all - "$exp"
+
+  [[ -n "$compconfig[expand_original]" && 
+     "$compconfig[expand_original]" = *last* ]] &&
+      compadd -UnQ -V _expand_original - "$word"
+
+  compstate[insert]=menu
+fi
+
+return 0
diff --git a/Completion/Core/_list b/Completion/Core/_list
new file mode 100644
index 000000000..099c6bc7b
--- /dev/null
+++ b/Completion/Core/_list
@@ -0,0 +1,61 @@
+#autoload
+
+# This completer function makes the other completer functions used
+# insert possible completions only after once the list has been
+# shown.
+#
+# Configuration keys:
+#
+#  list_condition
+#    If this key is unset or set to the empty string, this completer
+#    will delay the insertion of matches unconditionally. However,
+#    if this value is set, it should be set to an expression usable
+#    inside a $[...] arithmetical expression. In this case, delaying
+#    will be done if the expression evaluates to `1'.
+#    For example, with
+#
+#      compconf list_condition='NUMERIC != 1'
+#
+#    delaying will be done only if given an explicit numeric argument
+#    other than `1'.
+#
+#  list_word
+#    To find out if only listing should be done, the code normally
+#    compares the contents of the line with the contents the line
+#    had at the time of the last invocation. If this key is set to
+#    an non-empty string comparison is done using only the current
+#    word. So if it is set, attempting completion on a word equal
+#    to the one completion was called on the last time will not
+#    delay the generation of matches.
+
+local pre suf
+
+# Get the strings to compare.
+
+if [[ -z "$compconfig[list_word]" ]]; then
+  pre="$HISTNO$LBUFFER"
+  suf="$RBUFFER"
+else
+  pre="$PREFIX"
+  suf="$SUFFIX"
+fi
+
+# Should we only show a list now?
+
+if [[ ( -z "$compconfig[list_condition]" ||
+        "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ) &&
+      ( "$pre" != "$_list_prefix" || "$suf" != "$_list_suffix" ) ]]; then
+
+  # Yes. Tell the completion code about it and save the new values
+  # to compare the next time.
+
+  compstate[insert]=''
+  compstate[list]=list
+  compstate[force_list]=yes
+  _list_prefix="$pre"
+  _list_suffix="$suf"
+fi
+
+# We always return one, because we don't really do any work here.
+
+return 1
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 3571b712c..62e60a1cc 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -3,229 +3,56 @@
 # The main loop of the completion code. This is what is called when 
 # completion is attempted from the command line.
 #
-# This code will automatically try to correct the string on the line
-# based on the strings generated for the context if
-# `compconfig[correct]' is set and normal completion didn't yield any
-# matches. These corrected strings will be shown in a list and one can
-#cycle through them as in a menucompletion. To use this feature,
-#`compconfig[correct]' should be set to a number, specifying the 
-# maximum number of errors that should be accepted. If the string also
-# contains a `n' or `N', the code will use the numeric argument as the
-# maximum number of errors if a numeric argument was given. If no
-# numeric argument was given, the number from the value of
-# `compconfig[correct]' will be used. E.g. with `compconfig[correct]=2n'
-# two errors will be accepted, but if the user gives another number
-# with the numeric argument, this will be prefered. Also, with
-# `compconfig[correct]=0n',normally no automatic correction will be
-# tried, but if a numeric argument is given, automatic correction will
-# be used. Once the number of errors to accept is determined, the code
-# will repeatedly try to generate matches by allowing one error, two
-# errors, and so on. Independent of the number of errors the user
-# wants to accept, the code will allow only fewer errors than there
-# are characters in the string from the line.
-# The value of `compconfig[correct_orig]' is used to determine if the
-# original string should be included in the list (and thus be
-# presented to the user when cycling through the corrections). If it
-# is set to any non-empty value, the original string will be
-# offered. If it contains the sub-string `last', the original string
-# will apear as the last string when cycling through the corrections,
-# otherwise it will appear as the first one (so that the command line
-# does not change immediatly). Also, if the value of
-# `compconfig[correct_orig]' contains the sub-string `always', the
-# original string will always be included, whereas normally it is
-# included only if more than one possible correction was generated.
-# Finally, `compconfig[correct_prompt]' may be set to a string that
-# should be printed before the list of corrected strings when cycling
-# through them. This string may contain the control sequences `%n',
-# `%B', etc. known from the `-X' option of `compctl'. Also, the
-# sequence `%e' will be replaced by the number of errors accepted to
-# generate the corrected strings.
+# Configuration keys used:
+#
+#  completer
+#    This should be set to the names of the functions to generate the
+#    matches separated by colons. E.g. with
+#
+#      compconf completer=_complete:_correct:_approximate
+#
+#    the code will first try normal completion. If that doesn't yield
+#    any matches, correction is tried and if that doesn't yield
+#    anything either, correcting completion is attempted.
+#
+# These completer functions are only used when this function is called
+# without arguments. If arguments are given, they should be names of
+# completer functions which will then be called.
+
+
+# If you want to complete only set or unset options for the unsetopt
+# and setopt builtin, un-comment these lines:
+#
+#   local _set_options _unset_options
+#
+#   _set_options=("${(@f)$({ unsetopt kshoptionprint; setopt } 2>/dev/null)}")
+#   _unset_options=("${(@f)$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)}")
+#
+# This is needed because completion function may set options locally
+# which makes the output of setopt and unsetopt reflect a different
+# state than the global one for which you are completing.
 
-local comp name _comp_correct _correct_prompt comax
+
+local comp
 
 setopt localoptions nullglob rcexpandparam
 unsetopt markdirs globsubst shwordsplit nounset ksharrays
 
 # Special completion contexts after `~' and `='.
 
-if [[ -iprefix '=' ]]; then
+if compset -P 1 '\='; then
   compstate[context]=equal
-elif [[ "$PREFIX$SUFFIX" != */* && -iprefix '~' ]]; then
+elif [[ "$PREFIX" != */* && "$PREFIX[1]" = '~' ]]; then
+  compset -p 1
   compstate[context]=tilde
 fi
 
-# This is not an endless loop.
-
-while true; do
-
-  # An entry for `-first-' is the replacement for `compctl -T'
-  # Completion functions may set `_compskip' to any value to make the 
-  # main loops stop calling other completion functions.
-
-  comp="$_comps[-first-]"
-  if [[ ! -z "$comp" ]]; then
-    "$comp"
-    if (( $+_compskip )); then
-      unset _compskip
-      return
-    fi
-  fi
-
-  # For arguments and command names we use the `_normal' function.
-
-  if [[ "$compstate[context]" = command ]]; then
-    _normal
-  else
-    # Let's see if we have a special completion definition for the other
-    # possible contexts.
-
-    comp=''
-
-    case $compstate[context] in
-    equal)           comp="$_comps[-equal-]";;
-    tilde)           comp="$_comps[-tilde-]";;
-    redirect)        comp="$_comps[-redirect-]";;
-    math)            comp="$_comps[-math-]";;
-    subscript)       comp="$_comps[-subscript-]";;
-    value)           comp="$_comps[-value-]";;
-    array_value)     comp="$_comps[-array-value-]";;
-    condition)       comp="$_comps[-condition-]";;
-    parameter)       comp="$_comps[-parameter-]";;
-    brace_parameter) comp="$_comps[-brace-parameter-]";;
-    esac
-
-    # If not, we use default completion, if any.
-
-    [[ -z "$comp" ]] && comp="$_comps[-default-]"
-    [[ -z "$comp" ]] || "$comp"
-  fi
-
-  # Use automatic correction?
-
-  if (( $+compconfig[correct] )); then
-
-    # Do we have matches?
-    if (( compstate[nmatches] )); then
-
-      # Yes, were they added using correction? (More than one match?)
+# Get the names of the completers to use in the positional parameters.
 
-      if [[ -n "$_comp_correct" &&
-            ( "$compconfig[correct_orig]" = *always* ||
-	      compstate[nmatches] -gt 1 ) ]]; then
+(( $# )) || set ${(s.:.)compconfig[completer]}
 
-        if [[ "$compconfig[correct_orig]" = *last* ]]; then
-	  builtin compadd -V _correct_orig -nQ - "$PREFIX$SUFFIX"
-        elif [[ -n "$compconfig[correct_orig]" ]]; then
-	  builtin compadd -nQ - "$PREFIX$SUFFIX"
-	fi
+# And now just call the completer functions defined.
 
-	# If you always want to see the list of possible corrections,
-	# set `compstate[list]=list' here.
-
-	compstate[force_list]=list
-      fi
-      # Since we have matches, we don't want to try again.
-
-      break
-    fi
-
-    # No matches, so let's see if we already tried correction.
-
-    if [[ -n "$_comp_correct" ]]; then
-
-      # Yes, give up if we reached the maximum number of tries or the
-      # string from the line is too short, otherwise increment our 
-      # counter.
-
-      [[ _comp_correct -eq comax ||
-         "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct+1 ]] && break
-      (( _comp_correct++ ))
-
-      _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}"
-
-    elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then
-
-      # We don't try correction if the string is too short.
-
-      [[ "${#${:-$PREFIX$SUFFIX}}" -le 1 ]] && return
-
-      # No matches and no correction tried yet, but we just tried the
-      # last global match specification, so let's see if we should use
-      # correction now. First, get the maximum number of errors.
-
-      if [[ "$compconfig[correct]" = *[nN]* && NUMERIC -ne 1 ]]; then
-        # Prefer the numeric argument if that has a sensible value.
-        comax="$NUMERIC"
-      else
-        comax="${compconfig[correct]//[^0-9]}"
-      fi
-      # If the number of errors to accept is too small, give up.
-
-      [[ "$comax" -lt 1 ]] && break
-
-      # Otherwise temporarily define functions to use instead of
-      # the builtins that add matches. This is used to be able
-      # to stick the `(#a...)' into the right place (after an
-      # ignored prefix).
-
-      compadd() {
-        [[ "$*" != *-([a-zA-Z/]#|)U* &&
-           "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return
-
-        if [[ "$PREFIX" = \~*/* ]]; then
-	  PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
-	else
-          PREFIX="(#a${_comp_correct})$PREFIX"
-	fi
-	if [[ -n "$_correct_prompt" ]]; then
-	  builtin compadd -X "$_correct_prompt" -J _correct "$@"
-	else
-	  builtin compadd -J _correct "$@"
-	fi
-      }
-      compgen() {
-        [[ "$*" != *-([a-zA-Z/]#|)U* &&
-           "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return
-
-        if [[ "$PREFIX" = \~*/* ]]; then
-	  PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
-	else
-          PREFIX="(#a${_comp_correct})$PREFIX"
-	fi
-	if [[ -n "$_correct_prompt" ]]; then
-	  builtin compgen "$@" -X "$_correct_prompt" -J _correct
-	else
-	  builtin compgen "$@" -J _correct
-	fi
-      }
-      # Now initialise our counter. We also set `compstate[matcher]'
-      # to `-1'. This allows completion functions to use the simple
-      # `[[ compstate[matcher] -gt 1 ]] && return' to avoid being
-      # called for multiple global match specs and still be called 
-      # again when correction is done. Also, this makes it easy to
-      # test if correction is attempted since `compstate[matcher]'
-      # will never be set to a negative value by the completion code.
-
-      _comp_correct=1
-      compstate[matcher]=-1
-
-      _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}"
-
-      # We also need to set `extendedglob' and to make the completion
-      # code behave as if globcomplete were set.
-
-      setopt extendedglob
-      compstate[pattern_match]=yes
-    else
-      # We are still trying global match specifications...
-      break
-    fi
-  else
-    # No automatic correction to try, just give up.
-    break
-  fi
+for comp; do
+  "$comp" && return
 done
-
-# If we added wrapper functions, remove them.
-
-[[ -n "$_comp_correct" ]] && unfunction compadd compgen
diff --git a/Completion/Core/_match b/Completion/Core/_match
new file mode 100644
index 000000000..3c639935c
--- /dev/null
+++ b/Completion/Core/_match
@@ -0,0 +1,53 @@
+#autoload
+
+# This is intended to be used as a completer function after the normal
+# completer as in: `compconf completer=_complete:_match'.
+# It temporarily switches on pattern matching, allowing you to try 
+# completion on patterns without having to setopt glob_complete.
+#
+# Note, however, that this is only really useful if you don't use the
+# expand-or-complete function because otherwise the pattern will
+# be expanded using globbing.
+#
+# Configuration key used:
+#
+#  match_original
+#    If this is set to a `only', pattern matching will only be tried
+#    with the string from the line. If it is set to any other non-empty
+#    string, the original pattern will be tried first and if that yields
+#    no completions, matching will be tried again with a `*' inserted
+#    at the cursor position. If this key is not set or set to an empty
+#    string, matching will only be attempted with the `*' inserted.
+
+local tmp opm="$compstate[pattern_match]" ret=0
+
+# Do nothing if we don't have a pattern or there are still global
+# match specifications to try.
+
+tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
+[[ "$tmp:q" = "$tmp" ||
+   compstate[matcher] -ne compstate[total_matchers] ]] && return 1
+
+# Try completion without inserting a `*'?
+
+if [[ -n "$compconfig[match_original]" ]]; then
+  compstate[matcher]=-1
+  compstate[pattern_match]='-'
+  _complete && ret=1
+  compstate[pattern_match]="$opm"
+  compstate[matcher]="$compstate[total_matchers]"
+
+  (( ret )) && return 0
+fi
+
+# No completion with inserting `*'?
+
+[[ "$compconfig[match_original]" = only ]] && return 1
+
+compstate[matcher]=-1
+compstate[pattern_match]='*'
+_complete && ret=1
+compstate[pattern_match]="$opm"
+compstate[matcher]="$compstate[total_matchers]"
+
+return 1-ret
diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts
index 0c677aab7..ab9438494 100644
--- a/Completion/Core/_multi_parts
+++ b/Completion/Core/_multi_parts
@@ -45,7 +45,11 @@ fi
 # the original string in `orig'.
 
 if [[ $#compstate[pattern_match] -ne 0 ]]; then
-  patstr="${PREFIX}*${SUFFIX}*"
+  if [[ "${compstate[pattern_match]-*}" = \** ]]; then
+    str="${PREFIX}*${SUFFIX}*"
+  else
+    str="${PREFIX}${SUFFIX}"
+  fi
 else
   patstr="${PREFIX:q}*${SUFFIX:q}*"
 fi
@@ -145,7 +149,8 @@ if (( $#tmp1 )); then
   # found. Strings that have a separator will be added with a suffix.
 
   if [[ -z "$orig" && "$PREFIX$SUFFIX" != "$pref$orig" ]]; then
-    compadd -QU  "$group[@]" "$expl[@]" -i "$IPREFIX" -S '' - "${pref}${orig}"
+    compadd -QU  "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" -S '' - \
+            "${pref}${orig}"
   elif [[ -n "$menu" ]]; then
     if [[ "$orig" = *${sep}* ]]; then
       orig="${sep}${orig#*${sep}}"
@@ -154,20 +159,21 @@ if (( $#tmp1 )); then
     fi
     for i in "$matches[@]" ; do
       if [[ "$i" = *${sep}* ]]; then
-        compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
+        compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
 	        -p "$pref" -s "$orig" - "${i%%${sep}*}${sep}"
       else
-        compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
+        compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
 	        -p "$pref" -s "$orig" - "${i%%${sep}*}"
       fi
     done
   else
     for i in "$matches[@]" ; do
       if [[ "$i" = *${sep}* ]]; then
-        compadd -U -i "$IPREFIX" -p "$pref" -s "${i#*${sep}}" \
+        compadd -U -i "$IPREFIX" -I "$ISUFFIX" -p "$pref" -s "${i#*${sep}}" \
 	        "$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${sep}"
       else
-        compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -p "$pref" - "$i"
+        compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
+                -p "$pref" - "$i"
       fi
     done
   fi
@@ -201,8 +207,8 @@ elif [[ "$patstr" = *${sep}* ]]; then
       # the completion code together with our prefix and the rest of
       # the string from the line as the suffix.
 
-      compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" \
-              -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}"
+      compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \
+              -p "$pref" -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}"
       return 0
     fi
 
@@ -218,7 +224,8 @@ elif [[ "$patstr" = *${sep}* ]]; then
   # Finally, add the unambiguous prefix and the rest of the string
   # from the line.
 
-  compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" - "$orig"
+  compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \
+          -p "$pref" - "$orig"
 fi
 
 # This sets the return value to indicate that we added matches (or not).
diff --git a/Completion/Core/_options b/Completion/Core/_options
new file mode 100644
index 000000000..0a852e6ce
--- /dev/null
+++ b/Completion/Core/_options
@@ -0,0 +1,5 @@
+#autoload
+
+# This should be used to complete all option names.
+
+compgen "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters
new file mode 100644
index 000000000..0e8c548f7
--- /dev/null
+++ b/Completion/Core/_parameters
@@ -0,0 +1,8 @@
+#autoload
+
+# This should be used to complete parameter names if you need some of the
+# extra options of compadd. It first tries to complete only non-local
+# parameters. All arguments are given to compadd.
+
+compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }" ||
+    compadd "$@" - "${(@)${(@)${(@f)$(typeset)}%%\=*}##* }"
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 4c61ac7ef..54b04a368 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -12,6 +12,14 @@
 # like files with one of the suffixes in the `fignore' array in normal
 # completion.
 #
+# This function supports one configuration key:
+#
+#  path_expand
+#    If this is set to a non-empty string, the partially typed path
+#    from the line will be expanded as far as possible even if trailing
+#    pathname components can not be completed.
+#
+#
 # This function uses the helper functions `_match_test' and `_match_pattern'.
 
 # First see if we should generate matches for the global matcher in use.
@@ -20,14 +28,17 @@ _match_test _path_files || return 1
 
 # Yes, so...
 
-local nm prepaths str linepath realpath donepath patstr prepath testpath rest
+local nm str linepath realpath donepath patstr prepath testpath rest
 local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt
 local addpfx addsfx expl orig ostr nm=$compstate[nmatches] menu remsfx patlast
-local origflags mflags
+local origflags mflags tmp3 tmp4 exppaths
+
+typeset -U prepaths
 
 setopt localoptions nullglob rcexpandparam extendedglob
 unsetopt markdirs globsubst shwordsplit nounset
 
+exppaths=()
 prepaths=('')
 ignore=()
 group=()
@@ -102,7 +113,11 @@ fi
 # the prefix and the suffix. Then we see if we will do menucompletion.
 
 if [[ $#compstate[pattern_match] -ne 0 ]]; then
-  str="${PREFIX}*${SUFFIX}"
+  if [[ "${compstate[pattern_match]-*}" = \** ]]; then
+    str="${PREFIX}*${SUFFIX}"
+  else
+    str="${PREFIX}${SUFFIX}"
+  fi
 else
   str="${PREFIX:q}*${SUFFIX:q}"
   [[ "$str" = \\\~* ]] && str="$str[2,-1]"
@@ -200,7 +215,7 @@ origflags="$matchflags"
 # have special meaning for globbing, we remove them. But before that, we
 # add the pattern for matching any characters before a slash.
 
-patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-"
+patstr="$patstr:gs-/-*/-:gs/*.*./../:gs/**/*/:gs-.*/-./-"
 
 # We take the last pathname component from the pattern and store it in
 # `patlast', replacing `*'s in it with patterns that match any character
@@ -214,16 +229,16 @@ patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-"
 
 if [[ "$patstr" = */* ]]; then
   if [[ -n "$_comp_correct" && "${#orig##*/}" -le _comp_correct ]]; then
-    patlast="*/${origflags}${${patstr##*/}//\*/[^/]#}"
+    patlast="*/${origflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}"
   else
-    patlast="*/${matchflags}${${patstr##*/}//\*/[^/]#}"
+    patlast="*/${matchflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}"
   fi
   patstr="${patstr%/*}/"
 else
   if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then
-    patlast="${origflags}${patstr//\*/[^/]#}"
+    patlast="${origflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}"
   else
-    patlast="${matchflags}${patstr//\*/[^/]#}"
+    patlast="${matchflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}"
   fi
   patstr=""
 fi
@@ -234,7 +249,7 @@ fi
 # to `donepath'.
 
 while [[ "$orig" = */* ]] do
-  tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}$^pats )
+  tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}${^~pats} )
   tmp1=("${(@M)tmp1:#$~patlast}")
   [[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break
   donepath="$donepath${orig%%/*}/"
@@ -311,6 +326,24 @@ for prepath in "$prepaths[@]"; do
       # next `-W' path.
 
       if [[ $#collect -eq 0 ]]; then
+        # Before giving, we first try to get the longest expandable path-
+	# prefix, though. The result is stored in `exppaths'
+
+        tmp2=()
+	tmp3="$rest"
+	tmp4="${ostr##*/}"
+	ostr="${ostr%/*}"
+	while [[ "$tmp3" = */* ]]; do
+	  tmp2=( ${^tmp1}/${~mflags}${~tmp3} )
+	  if [[ $#tmp2 -eq 1 ]]; then
+	    exppaths=( "$exppaths[@]" "${tmp2[1]}${tmp4}" )
+	    exppaths=( "${(@)exppaths#${prepath}${realpath}}" )
+	    break;
+          fi
+	  tmp3="${tmp3%/*}"
+	  tmp4="${ostr##*/}/${tmp4}"
+	  ostr="${ostr%/*}"
+        done
         continue 2
       elif [[ $#collect -ne 1 ]]; then
         # If we have more than one possible match, this means that the
@@ -338,13 +371,14 @@ for prepath in "$prepaths[@]"; do
 
 	if [[ -n "$menu" ]]; then
           compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-                  -i "$IPREFIX" -p "$linepath${testpath:q}" \
+                  -i "$IPREFIX" -I "$ISUFFIX" -p "$linepath${testpath:q}" \
 		  -s "/${ostr#*/}" \
 		  -W "$tmp1" -f "$ignore[@]" - "${(@)${(@)collect%%/*}:q}"
 	else
           for i in $collect; do
             compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-	            -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
+	            -i "$IPREFIX" -I "$ISUFFIX" \
+                    -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
 		    -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}"
           done
 	fi
@@ -371,7 +405,8 @@ for prepath in "$prepaths[@]"; do
 
       if [[ $#tmp1 -ne $#tmp2 ]]; then
         compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \
-                -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${ostr#*/}" \
+                -i "$IPREFIX" -I "$ISUFFIX" \
+                -p "$linepath${testpath:q}" -s "/${ostr#*/}" \
 		- "${${tmp1#${prepath}${realpath}${testpath}}:q}"
         continue 2
       fi
@@ -399,8 +434,11 @@ for prepath in "$prepaths[@]"; do
   suffixes=( $str$^pats )
   suffixes=( "${(@)suffixes:gs.**.*.}" )
   tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
-  tmp2=("${(@M)tmp2:#$~patlast}")
-
+  if [[ "$tmp1" = */* && "$patlast" != \*/* ]]; then
+    tmp2=("${(@M)tmp2:#*${~patlast}}")
+  else
+    tmp2=("${(@M)tmp2:#$~patlast}")
+  fi
   if [[ $#tmp2 -eq 0 ]]; then
     # No match, insert the expanded path and add the original tail.
 
@@ -409,17 +447,29 @@ for prepath in "$prepaths[@]"; do
     [[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr"
 
     # But only if something changed.
-    [[ "$linepath$testpath$ostr" = "$PREFIX$SUFFIX" ]] && return 1
+    [[ "${PREFIX}${SUFFIX}" = $linepath$testpath$ostr(|/) ]] && return 1
 
     compadd -QU -S '' "$group[@]" "$expl[@]" \
-            -i "$IPREFIX" -f - "$linepath${testpath:q}$ostr"
+            -i "$IPREFIX" -I "$ISUFFIX" -f - "$linepath${testpath:q}$ostr"
   else
     compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \
-            -i "$IPREFIX" -p "$linepath${testpath:q}" -f "$ignore[@]" \
+            -i "$IPREFIX" -I "$ISUFFIX" \
+            -p "$linepath${testpath:q}" -f "$ignore[@]" \
 	    -W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}"
   fi
 done
 
+# If no matches were found but we have expanded paths which are different
+# from the original string, use them.
+
+exppaths=( "${(@)exppaths:#$orig}" )
+
+if [[ -n "$compconfig[path_expand]" &&
+      nm -eq compstate[nmatches] && $#exppaths -ne 0 ]]; then
+  compadd -UQ -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" - \
+          "${linepath}${(@)^exppaths}"
+fi
+
 # This sets the return value to indicate that we added matches (or not).
 
 [[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts
index c1cda2b9a..fc927163b 100644
--- a/Completion/Core/_sep_parts
+++ b/Completion/Core/_sep_parts
@@ -101,6 +101,8 @@ if [[ $# -le 1 || "$str" != *${2}* ]]; then
   _match_pattern _sep_parts test matchflags
   [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
 
+  [[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//"
+
   test="${matchflags}${test}"
   testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
   testarr=( "${(@)testarr:#}" )
@@ -131,6 +133,9 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do
   matchflags=""
   _match_pattern _sep_parts test matchflags
   [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+  [[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//"
+
   test="${matchflags}${test}"
 
   # We incrementally add suffixes by appending to them the seperators
@@ -163,7 +168,7 @@ done
 # Add the matches for each of the suffixes.
 for i in "$suffixes[@]"; do
   compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \
-          -i "$IPREFIX" -p "$prefix" -s "$i" - "$testarr[@]"
+          -i "$IPREFIX" -I "$ISUFFIX" -p "$prefix" -s "$i" - "$testarr[@]"
 done
 
 # This sets the return value to indicate that we added matches (or not).
diff --git a/Completion/Core/_set_options b/Completion/Core/_set_options
new file mode 100644
index 000000000..5f634a2cd
--- /dev/null
+++ b/Completion/Core/_set_options
@@ -0,0 +1,7 @@
+#autoload
+
+# Complete all set options. This relies on `_main_complete' to store the
+# names of the options that were set when it was called in the array
+# `_set_options'.
+
+compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options
diff --git a/Completion/Core/_unset_options b/Completion/Core/_unset_options
new file mode 100644
index 000000000..c5150c2e5
--- /dev/null
+++ b/Completion/Core/_unset_options
@@ -0,0 +1,7 @@
+#autoload
+
+# Complete all unset options. This relies on `_main_complete' to store the
+# names of the options that were set when it was called in the array
+# `_set_options'.
+
+compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options
diff --git a/Completion/Core/compdump b/Completion/Core/compdump
index 5fdee8c7a..6a46f3265 100644
--- a/Completion/Core/compdump
+++ b/Completion/Core/compdump
@@ -15,7 +15,7 @@
 # Print the number of files used for completion. This is used in compinit
 # to see if auto-dump should re-dump the dump-file.
 
-_d_file=${compconfig[dump_file]-${0:h}/compinit.dump}
+_d_file=${compconfig[dumpfile]-${0:h}/compinit.dump}
 
 typeset -U _d_files
 _d_files=( ${^~fpath}/_*~*~(N:t) )
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 466c80d36..19a0fd1ad 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -71,11 +71,12 @@ typeset -A compconfig
 
 # Standard initialisation for `compconfig'.
 
-(( $# )) && compconfig[dump_file]="$1"
-[[ -z "$compconfig[dump_file]" ]] && compconfig[dump_file]="$0.dump"
+(( $# )) && compconfig[dumpfile]="$1"
+[[ -z "$compconfig[dumpfile]" ]] && compconfig[dumpfile]="$0.dump"
 
+compconfig[correct_accept]=2n
 compconfig[correct_prompt]='correct to:'
-
+compconfig[completer]=_complete
 
 # This function is used to register or delete completion functions. For
 # registering completion functions, it is invoked with the name of the
@@ -246,10 +247,10 @@ _i_done=''
 
 # If we have a dump file, load it.
 
-if [[ -f "$compconfig[dump_file]" ]]; then
-  read -rA _i_line < "$compconfig[dump_file]"
+if [[ -f "$compconfig[dumpfile]" ]]; then
+  read -rA _i_line < "$compconfig[dumpfile]"
   if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
-    builtin . "$compconfig[dump_file]"
+    builtin . "$compconfig[dumpfile]"
     _i_done=yes
   fi
   unset _i_line