about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Completion/Base/Completer/_approximate108
1 files changed, 108 insertions, 0 deletions
diff --git a/Completion/Base/Completer/_approximate b/Completion/Base/Completer/_approximate
new file mode 100644
index 000000000..0b64db593
--- /dev/null
+++ b/Completion/Base/Completer/_approximate
@@ -0,0 +1,108 @@
+#autoload
+
+# This code will try to correct the string on the line based on the
+# 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 redef match
+local oldcontext="${curcontext}" opm="$compstate[pattern_match]"
+
+if [[ "$1" = -a* ]]; then
+  cfgacc="${1[3,-1]}"
+elif [[ "$1" = -a ]]; then
+  cfgacc="$2"
+else
+  zstyle -s ":completion:${curcontext}:" max-errors cfgacc ||
+      cfgacc='2 numeric'
+fi
+
+# Get the number of errors to accept.
+
+if [[ "$cfgacc" = *numeric* && ${NUMERIC:-1} -ne 1 ]]; then
+  # A numeric argument may mean that we should not try correction.
+
+  [[ "$cfgacc" = *not-numeric* ]] && return 1
+
+  # Prefer the numeric argument if that has a sensible value.
+
+  comax="${NUMERIC:-1}"
+else
+  comax="${cfgacc//[^0-9]}"
+fi
+
+# If the number of errors to accept is too small, give up.
+
+[[ "$comax" -lt 1 ]] && return 1
+
+_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).
+
+if (( ! $+functions[compadd] )); then
+  redef=yes
+  compadd() {
+    [[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
+       "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
+
+    ### This distinction doesn't seem to be needed anymore
+    # if [[ "$PREFIX" = \~*/* ]]; then
+    #   PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+    # else
+      PREFIX="(#a${_comp_correct})$PREFIX"
+    # fi
+    builtin compadd "$_correct_expl[@]" "$@"
+  }
+fi
+
+_comp_correct=1
+
+[[ -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 zstyle -t ":completion:${curcontext}:" insert-unambiguous &&
+       [[ "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
+      compstate[pattern_insert]=unambiguous
+    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 force' here.
+
+      [[ "$compstate[list]" != list* ]] &&
+          compstate[list]="$compstate[list] force"
+    fi
+    [[ -n "$redef" ]] && unfunction compadd
+    compstate[pattern_match]="$opm"
+
+    return 0
+  fi
+
+  [[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
+  (( _comp_correct++ ))
+done
+
+[[ -n "$redef" ]] && unfunction compadd
+compstate[pattern_match]="$opm"
+
+return 1