about summary refs log tree commit diff
path: root/Completion/Core/_main_complete
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:18:42 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:18:42 +0000
commit7a0415cfd70a02b2280d27556c6c54cef1c86e1a (patch)
tree37a88a1c4611ee37f2a3209873fc9a34a2624587 /Completion/Core/_main_complete
parent904b939cbd81a542303da2c58288b95b153106f5 (diff)
downloadzsh-7a0415cfd70a02b2280d27556c6c54cef1c86e1a.tar.gz
zsh-7a0415cfd70a02b2280d27556c6c54cef1c86e1a.tar.xz
zsh-7a0415cfd70a02b2280d27556c6c54cef1c86e1a.zip
zsh-3.1.5-pws-11 zsh-3.1.5-pws-11
Diffstat (limited to 'Completion/Core/_main_complete')
-rw-r--r--Completion/Core/_main_complete219
1 files changed, 185 insertions, 34 deletions
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index c7f5a5a96..34c5a3d3c 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -2,47 +2,198 @@
 
 # The main loop of the completion code. This is what is called when 
 # completion is attempted from the command line.
-# The completion code gives us the special variables and the arguments
-# from the command line are given as positional parameters.
+#
+# This code will automatically try to correct the string on the
+# line based on the strings generated for the context if the
+# parameter `COMPCORRECT' 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, `COMPCORRECT' 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
+# `COMPCORRECT' will be used. E.g. with `COMPCORRECT=2n' two errors
+# will be accepted, but if the user gives another number with the
+# numeric argument, this will be prefered. Also, with `COMPCORRECT=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.
+# If the parameter `CCORIG' is set (independent of the value), the
+# line will first be left unchanged and consecutive TABs cycle through 
+# the list.
+# When using automatic correction, one can also set the parameter
+# `CCPROMPT' to a string that will be shown when multiple
+# correction results are displayed and the code starts cycling
+# through them (this string is used with the `-X' option and thus may
+# contain the control sequences `%n', `%B',...).
 
-local comp name
+local comp name _comp_correct comax
 
 setopt localoptions nullglob rcexpandparam globdots
-unsetopt markdirs globsubst shwordsplit nounset
-
-# 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
+unsetopt markdirs globsubst shwordsplit nounset ksharrays
+
+# Special completion contexts after `~' and `='.
+
+if [[ -iprefix '=' ]]; then
+  compstate[context]=equal
+elif [[ "$PREFIX$SUFFIX" != */* && -iprefix '~' ]]; then
+  compstate[context]=tilde
 fi
 
-# For arguments we use the `_normal function.
+# This is not an endless loop.
 
-if [[ $CONTEXT == argument || $CONTEXT == command ]]; then
-  _normal "$@"
-else
-  # Let's see if we have a special completion definition for the other
-  # possible contexts.
+while true; do
 
-  comp=''
+  # 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.
 
-  case $CONTEXT in
-  redirect)  comp="$_comps[-redirect-]";;
-  math)      comp="$_comps[-math-]";;
-  subscript) comp="$_comps[-subscript-]";;
-  value)     comp="$_comps[-value-]";;
-  condition) comp="$_comps[-condition-]";;
-  esac
+  comp="$_comps[-first-]"
+  if [[ ! -z "$comp" ]]; then
+    "$comp"
+    if (( $+_compskip )); then
+      unset _compskip
+      return
+    fi
+  fi
 
-  # If not, we use default completion, if any.
+  # For arguments and command names we use the `_normal' function.
 
-  [[ -z "$comp" ]] && comp="$_comps[-default-]"
-  [[ -z "$comp" ]] || "$comp" "$@"
-fi
+  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 (( $+COMPCORRECT )); then
+
+    # Do we have matches?
+    if (( compstate[nmatches] )); then
+
+      # Yes, were they added using correction? (More than one match?)
+
+      if [[ -n "$_comp_correct" && compstate[nmatches] -gt 1 ]]; then
+
+        # If we got more than one string from correction, we add the 
+	# original string as a possible match, let it not be shown in
+	# the list, and probably display the `CCPROMPT'.
+
+        (( $+CCORIG )) && builtin compadd -nQ - "$PREFIX$SUFFIX"
+
+	# If you always want to see the list of possible corrections,
+	# set `compstate[list]=list' here.
+      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,
+      # otherwise increment our counter.
+
+      [[ _comp_correct -eq comax ]] && break
+      (( _comp_correct++ ))
+
+    elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then
+
+      # 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 [[ "$COMPCORRECT" = *[nN]* && NUMERIC -ne 1 ]]; then
+        # Prefer the numeric argument if that has a sensible value.
+        comax="$NUMERIC"
+      else
+        comax="${COMPCORRECT//[^0-9]}"
+      fi
+      # If the number of errors to accept is to 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() {
+        if [[ "$PREFIX" = \~*/* ]]; then
+	  PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+	else
+          PREFIX="(#a${_comp_correct})$PREFIX"
+	fi
+	if (( $+CCPROMPT )); then
+	  builtin compadd -X "$CCPROMPT" -J _correct "$@"
+	else
+	  builtin compadd -J _correct "$@"
+	fi
+      }
+      compgen() {
+        if [[ "$PREFIX" = \~*/* ]]; then
+	  PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+	else
+          PREFIX="(#a${_comp_correct})$PREFIX"
+	fi
+	if (( $+CCPROMPT )); then
+	  builtin compgen "$@" -X "$CCPROMPT" -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
+
+      # 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
+done
+
+# If we added wrapper functions, remove them.
+
+[[ -n "$_comp_correct" ]] && unfunction compadd compgen