about summary refs log tree commit diff
path: root/Completion
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
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')
-rw-r--r--Completion/Base/.distfiles2
-rw-r--r--Completion/Base/_brace_parameter10
-rw-r--r--Completion/Base/_condition2
-rw-r--r--Completion/Base/_long_options1
-rw-r--r--Completion/Base/_math18
-rw-r--r--Completion/Base/_tilde8
-rw-r--r--Completion/Builtins/_cd2
-rw-r--r--Completion/Builtins/_command3
-rw-r--r--Completion/Builtins/_hash4
-rw-r--r--Completion/Builtins/_kill2
-rw-r--r--Completion/Builtins/_sched2
-rw-r--r--Completion/Builtins/_setopt17
-rw-r--r--Completion/Builtins/_source3
-rw-r--r--Completion/Builtins/_unsetopt17
-rw-r--r--Completion/Builtins/_zmodload2
-rw-r--r--Completion/Commands/_correct_filename4
-rw-r--r--Completion/Commands/_most_recent_file2
-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
-rw-r--r--Completion/README243
-rw-r--r--Completion/User/_dd6
-rw-r--r--Completion/User/_find6
-rw-r--r--Completion/User/_mh4
-rw-r--r--Completion/User/_stty2
39 files changed, 1004 insertions, 299 deletions
diff --git a/Completion/Base/.distfiles b/Completion/Base/.distfiles
index 7e7635fa6..6f634c0b8 100644
--- a/Completion/Base/.distfiles
+++ b/Completion/Base/.distfiles
@@ -1,6 +1,6 @@
 DISTFILES_SRC='
     .distfiles 
     _brace_parameter _command_names _condition _default _equal
-    _long_options _match_pattern _match_pattern.orig _match_test _parameter
+    _long_options _match_pattern _match_test _math _parameter
     _precommand _redirect _subscript _tilde _vars 
 '
diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter
index 3fab8510a..3d663a777 100644
--- a/Completion/Base/_brace_parameter
+++ b/Completion/Base/_brace_parameter
@@ -1,5 +1,9 @@
 #defcomp -brace-parameter-
 
-# Simple but without spiffy suffix handling: compgen -v -S '} '
-
-compadd -S '} ' -r '-:?#%+=[/'  - "${(@)${(@)${(@f)$(set)}%%\=*}:gs/'//}"
+if [[ "$SUFFIX" = *\}* ]]; then
+  ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
+  SUFFIX="${SUFFIX%%\}*}"
+  _parameters -S '} ' -r '-:?#%+=[/'
+else
+  _parameters -S '} ' -r '-:?#%+=[/'
+fi
diff --git a/Completion/Base/_condition b/Completion/Base/_condition
index db1adfd9a..df1bf913e 100644
--- a/Completion/Base/_condition
+++ b/Completion/Base/_condition
@@ -3,7 +3,7 @@
 local prev="$words[CURRENT-1]"
 
 if [[ "$prev" = -o ]]; then
-  compgen -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}'
+  _options
 elif [[ "$prev" = -([no]t|ef) ]]; then
   _files
 else
diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options
index cc3175592..97b11f2dc 100644
--- a/Completion/Base/_long_options
+++ b/Completion/Base/_long_options
@@ -212,6 +212,7 @@ if [[ "$str" = *\=* ]]; then
   pat="${pre}*"
   patflags=''
   _match_pattern _long_options pat patflags
+
   [[ -n "$_comp_correct" ]] && patflags="$patflags(#a$_comp_correct)"
 
   # Then we walk through the array names. For each array we test if it 
diff --git a/Completion/Base/_math b/Completion/Base/_math
new file mode 100644
index 000000000..f7f4c360f
--- /dev/null
+++ b/Completion/Base/_math
@@ -0,0 +1,18 @@
+#defcomp -math-
+
+if [[ "$PREFIX" = *[^a-zA-Z0-9_]* ]]; then
+  IPREFIX="$IPREFIX${PREFIX%%[a-zA-Z0-9_]#}"
+  PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
+fi
+if [[ "$SUFFIX" = *[^a-zA-Z0-9_]* ]]; then
+  ISUFFIX="${SUFFIX##[a-zA-Z0-9_]#}$ISUFFIX"
+  SUFFIX="${SUFFIX%%[^a-zA-Z0-9_]*}"
+fi
+
+compgen -v
+#defcomp -math-
+
+IPREFIX="$IPREFIX${PREFIX%[a-zA-Z0-9_]*}"
+PREFIX="${PREFIX##*[^a-zA-Z0-9_]}"
+
+compgen -v
diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde
index aef575e19..c5ebb66d5 100644
--- a/Completion/Base/_tilde
+++ b/Completion/Base/_tilde
@@ -7,4 +7,10 @@
 #   `(( compstate[nmatches] )) || compgen -nu -qS/'
 # below that.
 
-compgen -nu -qS/
+if [[ "$SUFFIX" = */* ]]; then
+  ISUFFIX="/${SUFFIX#*/}$ISUFFIX"
+  SUFFIX="${SUFFIX%%/*}"
+  compgen -nu -S ''
+else
+  compgen -nu -qS/
+fi
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index 44443c3d5..a4fd56327 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -17,7 +17,7 @@ local pushdminus
 emulate -LR zsh
 setopt extendedglob
 
-if [[ -position 3 ]]; then
+if [[ CURRENT -eq 3 ]]; then
   # cd old new: look for old in $PWD and see what can replace it
   local rep
   # Get possible completions using word in position 2
diff --git a/Completion/Builtins/_command b/Completion/Builtins/_command
index 47eb0d667..4facceb12 100644
--- a/Completion/Builtins/_command
+++ b/Completion/Builtins/_command
@@ -1,6 +1,7 @@
 #defcomp command
 
-if [[ -position 3 -1 ]]; then
+if [[ CURRENT -ge 3 ]]; then
+  compset -n 2
   _normal
 else
   compgen -em
diff --git a/Completion/Builtins/_hash b/Completion/Builtins/_hash
index 8c100b801..4d4ba4244 100644
--- a/Completion/Builtins/_hash
+++ b/Completion/Builtins/_hash
@@ -1,12 +1,12 @@
 #defcomp hash
 
 if [[ "$words[2]" = -*d* ]]; then
-  if [[ -string 1 '=' ]]; then
+  if compset -P 1 '*\='; then
     _path_files -g '*(-/)'
   else
     compgen -n -q -S '='
   fi
-elif [[ -string 1 '=' ]]; then
+elif compset -P 1 '*\='; then
   _files -/g '*(*)'
 else
   compgen -m -q -S '='
diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill
index 36a23ccb2..0b0f5c188 100644
--- a/Completion/Builtins/_kill
+++ b/Completion/Builtins/_kill
@@ -2,7 +2,7 @@
 
 local list
 
-if [[ -iprefix '-' ]]; then
+if compset -P 1 -; then
   compgen -k "($signals[1,-3])"
 else
   local ret=1
diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched
index 62cdbb070..5fba71eac 100644
--- a/Completion/Builtins/_sched
+++ b/Completion/Builtins/_sched
@@ -1,3 +1,3 @@
 #defcomp sched
 
-[[ -position 3 -1 ]] && _normal
+compset -n 3 && _normal
diff --git a/Completion/Builtins/_setopt b/Completion/Builtins/_setopt
index b458cb2b0..e5a6c054f 100644
--- a/Completion/Builtins/_setopt
+++ b/Completion/Builtins/_setopt
@@ -1,11 +1,10 @@
 #defcomp setopt
 
-local nm=$compstate[nmatches] ret=1
-
-compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-         -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' && ret=0
-
-[[ compstate[nmatches] -eq nm ]] &&
-    compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0
-
-return ret
+# If you first want to complete only unset options, un-comment the lines
+# setting the _unset_options  array and then use:
+#
+#   _unset_options || _options
+#
+# here.
+
+_options
diff --git a/Completion/Builtins/_source b/Completion/Builtins/_source
index 1bbbf15a4..efac4f32b 100644
--- a/Completion/Builtins/_source
+++ b/Completion/Builtins/_source
@@ -1,6 +1,7 @@
 #defcomp source
 
-if [[ -position 3 -1 ]]; then
+if [[ CURRENT -ge 3 ]]; then
+  compset -n 2
   _normal
 else
   _files
diff --git a/Completion/Builtins/_unsetopt b/Completion/Builtins/_unsetopt
index 1194e28a7..cdc2ab9f3 100644
--- a/Completion/Builtins/_unsetopt
+++ b/Completion/Builtins/_unsetopt
@@ -1,11 +1,10 @@
 #defcomp unsetopt
 
-local nm=$compstate[nmatches] ret=1
-
-compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-         -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' && ret=0
-
-[[ compstate[nmatches] -eq nm ]] &&
-    compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0
-
-return ret
+# If you first want to complete only unset options, uncomment the lines
+# setting the _set_options  array and then use:
+#
+#   _set_options || _options
+#
+# here.
+
+_options
diff --git a/Completion/Builtins/_zmodload b/Completion/Builtins/_zmodload
index 4259adf06..9247ba0ce 100644
--- a/Completion/Builtins/_zmodload
+++ b/Completion/Builtins/_zmodload
@@ -2,7 +2,7 @@
 
 local fl="$words[2]"
 
-if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && -position 4 -1 ]]; then
+if [[ "$fl" = -*(a*u|u*a)* || "$fl" = -*a* && CURRENT -ge 4 ]]; then
   compgen -B
 elif [[ "$fl" = -*u* ]]; then
   compgen -s '$(zmodload)'
diff --git a/Completion/Commands/_correct_filename b/Completion/Commands/_correct_filename
index 27295738c..72bac5f1b 100644
--- a/Completion/Commands/_correct_filename
+++ b/Completion/Commands/_correct_filename
@@ -45,7 +45,7 @@ fi
 if [[ -z $testcmd && -e "$file" ]] ||
   { [[ -n $testcmd ]] && whence "$file" >&/dev/null }; then
   if [[ -n $WIDGET ]]; then
-    compadd -QUf -i "$IPREFIX" "${file/#$etilde/$tilde}"
+    compadd -QUf -i "$IPREFIX" -I "$ISUFFIX" "${file/#$etilde/$tilde}"
     [[ -n "$compstate[insert]" ]] && compstate[insert]=menu
   else
     print "$file"
@@ -65,7 +65,7 @@ done
 (( $#trylist )) || return 1
 
 if [[ -n $WIDGET ]]; then
-  compadd -QUf -i "$IPREFIX" "${trylist[@]/#$etilde/$tilde}"
+  compadd -QUf -i "$IPREFIX" -I "$ISUFFIX" "${trylist[@]/#$etilde/$tilde}"
   [[ -n "$compstate[insert]" ]] && compstate[insert]=menu
 else
   print "$IPREFIX${^trylist[@]}"
diff --git a/Completion/Commands/_most_recent_file b/Completion/Commands/_most_recent_file
index df35ecba7..5bd737fd2 100644
--- a/Completion/Commands/_most_recent_file
+++ b/Completion/Commands/_most_recent_file
@@ -19,4 +19,4 @@ if [[ $PREFIX = \~*/* ]]; then
 else
   file=($~PREFIX*$~SUFFIX(om[$NUMERIC]N))
 fi
-(( $#file )) && compadd -U -f -Q $file
+(( $#file )) && compadd -U -i "$IPREFIX" -I "$ISUFFIX" -f -Q $file
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
diff --git a/Completion/README b/Completion/README
index 931d14355..bf677066a 100644
--- a/Completion/README
+++ b/Completion/README
@@ -14,7 +14,7 @@ The name of the file to use may be given as an extra argument.
 This will rebind any keys which do completion to use the new system.
 For more detailed instructions, including how to add new completions, see
 the top of Core/compinit. For information about how to configure the code,
-see the comment at the top of Core/_main_complete.
+see the section below.
 
 The subdirectories contain:
 
@@ -30,32 +30,61 @@ Core:
     This dumps the completions status for faster initialisation.  The
     easiest way of doing this is to use the -d option to compinit rather
     than calling compdump directly.
-  _sep_parts
-    Utility used for completing words with multiple separate parts, such as
-    `<user>@<host>'
-  _multi_parts
-    Utility for completion parts of words given a separator character and 
-    a list of words.
+  _approximate
+    A completer function that does correcting completion.
   _compalso
     Utility for calling a function to add additional completions to an
     already existing set.
+  _complete
+    The main completer function that generates the completions by calling
+    the context and command specific functions.
+  _correct
+    A completer function that attempts correction on the word from the
+    line. Unlike _approximate this does only correction, not completion.
+  _expand
+    A completer function for expanding the word on the line.
   _files
     A frontend to _path_files which will default to any old file if the
     specified file was not found.
+  _list
+    A completer function that allows showing only a list on the first
+    TAB and insert completions on the second one.
+  _match
+    A completer function that temporarily swicthes on pattern matching
+    when comparing the string from the line with possible completions.
   _main_complete
     The main entry point called by the key bindings which compinit sets
-    up (the main `completion widget' in zsh jargon).
+    up (the main `completion widget' in zsh jargon). This mainly calls
+    completer functions like _complete, either those given as arguments
+    or (if it is called without arguments) those from the completer
+    configuration key (see below).
+  _multi_parts
+    Utility for completion parts of words given a separator character and 
+    a list of words.
   _normal
     The function called by _main_complete to handle the most common
     cases, such as completing a command name or its arguments.  This
     function dispatches to the various other functions for individual
     commands.  (Actually, the system is fairly context-sensitive, so
     it is wider than just command+argument.)
+  _options
+    Utility to complete option names, allowing the optional `no' prefix
+    and correctly handling upper case letters and underscores.
+  _parameters
+    This can be used to complete parameter names if you need some of the
+    options of compadd not supported by compgen.
   _path_files
     The function usually called to complete filenames and directories.  It
     replaces the standard -f, -g and -/ options for the basic completion
     commands:  it can do various extra tricks, such as expanding a whole
     path at once, e.g. F/C/C/_p<TAB> -> Functions/Completion/Core/_path_files
+  _sep_parts
+    Utility used for completing words with multiple separate parts, such as
+    `<user>@<host>'
+  _set_options
+  _unset_options
+    These can be used to complete only set or unset options. For this to
+    work, you'll have to un-comment a few lines in _main_complete.
 Base:
   You will almost certainly want these files, too, which handle standard
   tasks like completing files.  However, you may want to edit them for
@@ -127,3 +156,201 @@ Commands:
   _most_recent_file, bound to \C-xm
     Insert the name of the most recent file matching the pattern
     so far on the command line.
+
+
+Configuration
+
+You can configure several aspects of the completion functions and the
+overall completion behavior using the compconf shell function defined
+in compinit. This function gets any number of arguments of the form
+`key=value', where `key' is one of the keys described below and `value'
+is any string. Most configuration keys are defined by the completer
+functions.
+
+The completion widget function _main_complete currently understands
+one configuration key:
+
+  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.
+
+The keys understood by the _approximate completer function are:
+
+  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. The forms beginning with `correct' are also used by the
+_correct completer function, and this function uses only them, not
+the ones starting with `approximate'. This allows one to give
+different value to be used with correction and correcting
+completion. For example, with:
+
+  compconf completer=_complete:_correct:_approximate
+  compconf correct_accept='2n!' approximate_accept=3n
+
+correction will accept up to two errors. If a numeric argument is
+given, correction will not be used, but correcting completion will
+and it will accept as many errors as given by the numeric argument.
+Without a numeric argument first correction and then correcting
+completion will be tried, with the first one accepting two errors 
+and the second one accepting three errors.
+
+The _match completer function, which allows to give patterns on the
+command line and complete all strings matching it from the set of
+possible completions, understands the following key:
+
+  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.
+
+The _expand completer allows one to do expansion on the word from the
+line. Note that you may either want to use the configuration keys or
+not use this completer at all if you also use the _match completer
+because the _expand completer will otherwise expand patterns before
+they are seen by the _match completer.
+Configuration keys supported are:
+
+  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.
+
+The _list completer allows one to delay the insertion of matches until
+completion is attempted a second time without the word on the line 
+being changed. On the first attempt, only the list of matches will
+be shown. Configuration keys understood are:
+
+  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.
+
+For more information about what the completers do, see the files
+containing them (_complete, _correct, _approximate, _match, and
+_expand in the Core directory).
+
+The _path_files function used to complete filenames has 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.
diff --git a/Completion/User/_dd b/Completion/User/_dd
index 63ae40f50..6b07a382c 100644
--- a/Completion/User/_dd
+++ b/Completion/User/_dd
@@ -1,12 +1,12 @@
 #defcomp dd
 
-if [[ -iprefix conv= ]]; then
+if compset -P 1 'conv\='; then
   # If there's a comma present, ignore up to the last one.  The
   # test alone will have that effect.
-  [[ -string , ]]
+  compset -p '*,'
   compgen -S, -q \
       -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)'
-elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then
+elif compset -P 1 '[io]f\='; then
   _files
 else
   compgen -S '=' -k '(if of ibs obs bs cbs skip files seek count conv)'
diff --git a/Completion/User/_find b/Completion/User/_find
index cb637fc26..13d1d797e 100644
--- a/Completion/User/_find
+++ b/Completion/User/_find
@@ -2,14 +2,14 @@
 
 local prev="$words[CURRENT-1]"
 
-if [[ -mbetween -(ok|exec) \\\; ]]; then
+if compset -N '-(ok|exec)' '\;' then
   _normal
-elif [[ -iprefix - ]]; then
+elif compset -P 1 -; then
   compgen -s 'daystart {max,min,}depth follow noleaf version xdev \
     {a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
     {i,}{l,}name {no,}{user,group} path perm regex size true uid used \
     exec {f,}print{f,0,} ok prune ls'
-elif [[ -position 2 ]]; then
+elif [[ CURRENT -eq 2 ]]; then
   local ret=1
 
   compgen -g '. ..' && ret=0
diff --git a/Completion/User/_mh b/Completion/User/_mh
index c6c018220..ab78468d8 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -13,7 +13,7 @@ local prev="$words[CURRENT-1]"
 # To be on the safe side, check this exists and if not, get it anyway.
 [[ -d $mymhdir ]] || mymhdir=$(mhpath +)
 
-if [[ -iprefix - ]]; then
+if compset -P 1 -; then
   # get list of options, which MH commands can generate themselves
   # awk is just too icky to use for this, sorry.  send me one if
   # you come up with it.
@@ -23,7 +23,7 @@ if [[ -iprefix - ]]; then
     print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n";
   }')
   return
-elif [[ -iprefix '+' || -iprefix '@' || "$prev" = -draftfolder ]]; then
+elif compset -P 1 '[+@] || [ "$prev" = -draftfolder ]]; then
   # Complete folder names.
   local mhpath
 
diff --git a/Completion/User/_stty b/Completion/User/_stty
index d32d6bdff..73c860d54 100644
--- a/Completion/User/_stty
+++ b/Completion/User/_stty
@@ -5,7 +5,7 @@ if [[ "$words[CURRENT-1]" = \
 then
      compadd -Q '^-' '^h' '^?' '^c' '^u'
 else
-  [[ -string '-' || -string '+' ]]
+  compset -P '[-+]'
   compadd rows columns intr quit erase kill eof eol \
     eol2 start stop susp dsusp reprint discard werase lnext \
     parenb parodd cs8 cstopb hupcl cread clocal parext \