about summary refs log tree commit diff
path: root/Completion/Core/_approximate
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Core/_approximate')
-rw-r--r--Completion/Core/_approximate192
1 files changed, 46 insertions, 146 deletions
diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate
index 1b40f7cbf..0815a308e 100644
--- a/Completion/Core/_approximate
+++ b/Completion/Core/_approximate
@@ -1,102 +1,30 @@
 #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
+# strings generated for the context. These corrected strings will be
+# shown in a list and one can cycle through them as in a menucompletion
+# or get the corrected prefix.
+
+# We don't try correction if the string is too short or we have tried it
+# already.
+
+[[ _matcher_num -gt 1 || "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
+
+local _comp_correct _correct_expl comax cfgacc
+local oldcontext="${curcontext}" opm="$compstate[pattern_match]"
+
+zstyle -s ":completion:${curcontext}:" max-errors cfgacc || cfgacc='2 numeric'
 
 # Get the number of errors to accept.
 
-if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then
-  # Stop if we also have a `!'.
+if [[ "$cfgacc" = *numeric* && ${NUMERIC:-1} -ne 1 ]]; then
+  # A numeric argument may mean that we should not try correction.
 
-  [[ "$cfgacc" = *\!* ]] && return 1
+  [[ "$cfgacc" = *not-numeric* ]] && return 1
 
   # Prefer the numeric argument if that has a sensible value.
 
-  comax="$NUMERIC"
+  comax="${NUMERIC:-1}"
 else
   comax="${cfgacc//[^0-9]}"
 fi
@@ -105,13 +33,15 @@ fi
 
 [[ "$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
+_tags corrections original
+
+# Otherwise temporarily define a function to use instead of
+# the builtin that adds matches. This is used to be able
+# to stick the `(#a...)' in the right place (after an
 # ignored prefix).
 
 compadd() {
-  [[ "$*" != *-([a-zA-Z/]#|)U* &&
+  [[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
      "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
 
   if [[ "$PREFIX" = \~*/* ]]; then
@@ -119,79 +49,49 @@ compadd() {
   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
+  builtin compadd "$_correct_expl[@]" "$@"
 }
 
-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
+  curcontext="${oldcontext/(#b)([^:]#:[^:]#:)/${match[1][1,-2]}-${_comp_correct}:}"
+
+  _description corrections _correct_expl corrections \
+               "e:$_comp_correct" "o:$PREFIX$SUFFIX"
+
   if _complete; then
-    if [[ "$cfgins" = unambig* &&
-          "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
+    if zstyle -t ":completion:${curcontext}:" insert-unambiguous &&
+       [[ "${#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
+    elif _requested original &&
+         { [[ compstate[nmatches] -gt 1 ]] ||
+           zstyle -t ":completion:${curcontext}:" original }; then
+      local expl
+
+      _description -V original expl original
+
+      builtin compadd "$expl[@]" -U -Q - "$PREFIX$SUFFIX"
 
       # If you always want to see the list of possible corrections,
-      # set `compstate[list]=list' here.
+      # set `compstate[list]=list force' here.
 
-      compstate[force_list]=list
+      [[ "$compstate[list]" != list* ]] &&
+          compstate[list]="$compstate[list] force"
     fi
-    compstate[matcher]="$compstate[total_matchers]"
-    unfunction compadd compgen
+    unfunction compadd
+    compstate[pattern_match]="$opm"
 
     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
+unfunction compadd
+compstate[pattern_match]="$opm"
 
 return 1