about summary refs log tree commit diff
path: root/Completion/Base
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Base')
-rw-r--r--Completion/Base/Completer/_approximate48
-rw-r--r--Completion/Base/Completer/_prefix9
-rw-r--r--Completion/Base/Core/_main_complete22
-rw-r--r--Completion/Base/Utility/_numbers2
-rw-r--r--Completion/Base/Utility/_shadow97
-rw-r--r--Completion/Base/Utility/_values2
-rw-r--r--Completion/Base/Widget/_complete_debug2
-rw-r--r--Completion/Base/Widget/_complete_help3
8 files changed, 135 insertions, 50 deletions
diff --git a/Completion/Base/Completer/_approximate b/Completion/Base/Completer/_approximate
index dcd8b2776..96860b5a7 100644
--- a/Completion/Base/Completer/_approximate
+++ b/Completion/Base/Completer/_approximate
@@ -12,7 +12,6 @@
 
 local _comp_correct _correct_expl _correct_group comax cfgacc match
 local oldcontext="${curcontext}" opm="$compstate[pattern_match]"
-local dounfunction
 integer ret=1
 
 if [[ "$1" = -a* ]]; then
@@ -44,34 +43,31 @@ fi
 
 _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).
+# 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).
 #
-# Current shell structure for use with "always", to make sure
-# we unfunction the compadd.
+# Current shell structure for use with "always", to make sure we unfunction our
+# compadd and restore any compadd function defined previously.
 {
-if (( ! $+functions[compadd] )); then
-  dounfunction=1
-  compadd() {
-    local ppre="$argv[(I)-p]"
-
-    [[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
-       "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
-
-    if [[ "$PREFIX" = \~* && ( ppre -eq 0 || "$argv[ppre+1]" != \~* ) ]]; then
-      PREFIX="~(#a${_comp_correct})${PREFIX[2,-1]}"
-    else
-      PREFIX="(#a${_comp_correct})$PREFIX"
-    fi
+_shadow -s _approximate compadd
+compadd() {
+  local ppre="$argv[(I)-p]"
 
-    (( $_correct_group && ${${argv[1,(r)-(|-)]}[(I)-*[JV]]} )) &&
-        _correct_expl[_correct_group]=${argv[1,(r)-(-|)][(R)-*[JV]]}
+  [[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
+      "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
 
-    builtin compadd "$_correct_expl[@]" "$@"
-  }
-fi
+  if [[ "$PREFIX" = \~* && ( ppre -eq 0 || "$argv[ppre+1]" != \~* ) ]]; then
+    PREFIX="~(#a${_comp_correct})${PREFIX[2,-1]}"
+  else
+    PREFIX="(#a${_comp_correct})$PREFIX"
+  fi
+
+  (( $_correct_group && ${${argv[1,(r)-(|-)]}[(I)-*[JV]]} )) &&
+      _correct_expl[_correct_group]=${argv[1,(r)-(-|)][(R)-*[JV]]}
+
+  compadd@_approximate "$_correct_expl[@]" "$@"
+}
 
 _comp_correct=1
 
@@ -115,7 +111,7 @@ while [[ _comp_correct -le comax ]]; do
 done
 
 } always {
-    [[ -n $dounfunction ]] && (( $+functions[compadd] )) && unfunction compadd
+  _unshadow
 }
 
 (( ret == 0 )) && return 0
diff --git a/Completion/Base/Completer/_prefix b/Completion/Base/Completer/_prefix
index 74be5f47d..aea2f7863 100644
--- a/Completion/Base/Completer/_prefix
+++ b/Completion/Base/Completer/_prefix
@@ -49,13 +49,8 @@ for tmp in "$comp[@]"; do
     fi
 
     if [[ "$tmp" != _prefix ]] && "$tmp"; then
-      [[ compstate[nmatches] -gt 1 ]] && return 0
-      compadd -U -i "$IPREFIX" -I "$ISUFFIX" - "${compstate[unambiguous]%$suf}x"
-      compstate[list]=
-      if [[ -n $compstate[unambiguous] ]]; then
-        compstate[insert]=unambiguous
-      else
-        compstate[insert]=0
+      if [[ -n $compstate[old_list] || ${compstate[unambiguous]%$suf} == $PREFIX ]]; then
+        compstate[to_end]=match
       fi
       return 0
     fi
diff --git a/Completion/Base/Core/_main_complete b/Completion/Base/Core/_main_complete
index 169ca1f40..408a66ee3 100644
--- a/Completion/Base/Core/_main_complete
+++ b/Completion/Base/Core/_main_complete
@@ -93,19 +93,15 @@ fi
 if [[ -z "$compstate[quote]" ]]; then
   if [[ -o equals ]] && compset -P 1 '='; then
     compstate[context]=equal
-  elif [[ "$PREFIX" != */* && "$PREFIX[1]" = '~' ]]; then
-    if [[ "$PREFIX" = '~['[^\]]# ]]; then
-      # Inside ~[...] should be treated as a subscript.
-      compset -p 2
-      # To be consistent, we ignore all but the contents of the square
-      # brackets.
-      compset -S '\]*'
-      compstate[context]=subscript
-      [[ -n $_comps[-subscript-] ]] && $_comps[-subscript-] && return
-    else
-      compset -p 1
-      compstate[context]=tilde
-    fi
+  elif [[ "$PREFIX" = \~\[[^]]# ]]; then
+    # Inside ~[...] should be treated as a subscript.
+    compset -p 2
+    # To be consistent, we ignore all but the contents of the square brackets.
+    compset -S '\]*'
+    compstate[context]=subscript
+  elif [[ "$PREFIX" = \~[^/]# ]]; then
+    compset -p 1
+    compstate[context]=tilde
   fi
 fi
 
diff --git a/Completion/Base/Utility/_numbers b/Completion/Base/Utility/_numbers
index 97bb8b4c8..069fc75a4 100644
--- a/Completion/Base/Utility/_numbers
+++ b/Completion/Base/Utility/_numbers
@@ -73,7 +73,7 @@ elif [[ -prefix $~pat || $PREFIX = $~partial ]]; then
     zformat -f suffix "$suffixfmt" "x:${${argv[i+1]#:}%%:*}" \
         "X:${${argv[i+1]#:}#*:}" "d:${#${argv[i+1]}[1]#:}" \
 	i:i r:$(( $# - i - 1))
-    suffixes+="$suffix"
+    suffixes+="${suffix//\%/%%}"
   done
   [[ -n $suffixes ]] && formats+=( x:$suffixes )
 
diff --git a/Completion/Base/Utility/_shadow b/Completion/Base/Utility/_shadow
new file mode 100644
index 000000000..9e78af38f
--- /dev/null
+++ b/Completion/Base/Utility/_shadow
@@ -0,0 +1,97 @@
+#autoload
+
+## Recommended usage:
+#  {
+#    _shadow fname
+#    function fname {
+#      # Do your new thing
+#    }
+#    # Invoke callers of fname
+#  } always {
+#    _unshadow
+#  }
+## Alternate usage:
+# {
+#   _shadow -s suffix fname
+#   function fname {
+#     # Do other stuff
+#     fname@suffix new args for fname
+#   }
+#   # Invoke callers of fname
+# } always {
+#   _unshadow
+# }
+##
+
+# BUGS:
+# * `functions -c` acts like `autoload +X`
+# * name collisions are possible in alternate usage
+# * functions that examine $0 probably misfire
+
+zmodload zsh/parameter # Or what?
+
+# This probably never comes up, but protect ourself from recursive call
+# chains that may duplicate the top elements of $funcstack by creating
+# a counter of _shadow calls and using it to make shadow names unique.
+builtin typeset -gHi .shadow.depth=0
+builtin typeset -gHa .shadow.stack
+
+# Create a copy of each fname so that a caller may redefine
+_shadow() {
+  emulate -L zsh
+  local -A fsfx=( -s ${funcstack[2]}:${functrace[2]}:$((.shadow.depth+1)) )
+  local fname shadowname
+  local -a fnames
+  zparseopts -K -A fsfx -D s:
+  for fname; do
+    shadowname=${fname}@${fsfx[-s]}
+    if (( ${+functions[$shadowname]} ))
+    then
+      # Called again with the same -s, just ignore it
+      continue
+    elif (( ${+functions[$fname]} ))
+    then
+      builtin functions -c -- $fname $shadowname
+      fnames+=(f@$fname)
+    elif (( ${+builtins[$fname]} ))
+    then
+      eval "function -- ${(q-)shadowname} { builtin ${(q-)fname} \"\$@\" }"
+      fnames+=(b@$fname)
+    else
+      eval "function -- ${(q-)shadowname} { command ${(q-)fname} \"\$@\" }"
+      fnames+=(c@$fname)
+    fi
+  done
+  [[ -z $REPLY ]] && REPLY=${fsfx[-s]}
+  builtin set -A .shadow.stack ${fsfx[-s]} $fnames -- ${.shadow.stack}
+  ((.shadow.depth++))
+}
+
+# Remove the redefined function and shadowing name
+_unshadow() {
+  emulate -L zsh
+  local fname shadowname fsfx=${.shadow.stack[1]}
+  local -a fnames
+  [[ -n $fsfx ]] || return 1
+  shift .shadow.stack
+  while [[ ${.shadow.stack[1]?no shadows} != -- ]]; do
+    fname=${.shadow.stack[1]#?@}
+    shadowname=${fname}@${fsfx}
+    if (( ${+functions[$fname]} )); then
+      builtin unfunction -- $fname
+    fi
+    case ${.shadow.stack[1]} in
+      (f@*) builtin functions -c -- $shadowname $fname ;&
+      ([bc]@*) builtin unfunction -- $shadowname ;;
+    esac
+    shift .shadow.stack
+  done
+  [[ -z $REPLY ]] && REPLY=$fsfx
+  shift .shadow.stack
+  ((.shadow.depth--))
+}
+
+# This is tricky.  When we call _shadow recursively from autoload,
+# there's an extra level of stack in $functrace that will confuse
+# the later call to _unshadow.  Fool ourself into working correctly.
+(( ARGC )) && _shadow -s ${funcstack[2]}:${functrace[2]}:1 "$@"
diff --git a/Completion/Base/Utility/_values b/Completion/Base/Utility/_values
index 688ada848..5ed79e890 100644
--- a/Completion/Base/Utility/_values
+++ b/Completion/Base/Utility/_values
@@ -60,7 +60,7 @@ if compvalues -i "$keep[@]" "$@"; then
       _describe "$descr" \
         noargs "$sep[@]" -M 'r:|[_-]=* r:|=*' -- \
         args -S "${argsep}" -M 'r:|[_-]=* r:|=*' -- \
-        opts -qS "${argsep}" -r "${argsep}${sep} \\t\\n\\-" -M 'r:|[_-]=* r:|=*'
+        opts -qS "${argsep}" -r "${argsep}${sep[2]} \\t\\n\\-" -M 'r:|[_-]=* r:|=*'
 
       curcontext="$oldcontext"
 
diff --git a/Completion/Base/Widget/_complete_debug b/Completion/Base/Widget/_complete_debug
index 94fd4accd..d8b1bd837 100644
--- a/Completion/Base/Widget/_complete_debug
+++ b/Completion/Base/Widget/_complete_debug
@@ -19,7 +19,7 @@ integer debug_fd=-1
     setopt localoptions no_ignorebraces
     debug_indent=( '%'{3..20}'(e. .)' )
   }
-  local PROMPT4 PS4="${(j::)debug_indent}+%N:%i> "
+  local PROMPT4="$PROMPT4" PS4="${(j::)debug_indent}+%N:%i> "
   setopt xtrace
   : $ZSH_NAME $ZSH_VERSION
   ${1:-_main_complete}
diff --git a/Completion/Base/Widget/_complete_help b/Completion/Base/Widget/_complete_help
index 69855de9d..da5947e7f 100644
--- a/Completion/Base/Widget/_complete_help
+++ b/Completion/Base/Widget/_complete_help
@@ -10,6 +10,7 @@ _complete_help() {
   local -H _help_filter_funcstack="alternative|call_function|describe|dispatch|wanted|requested|all_labels|next_label"
 
   {
+    _shadow compadd compcall zstyle
     compadd() { return 1 }
     compcall() { _help_sort_tags use-compctl }
     zstyle() {
@@ -43,7 +44,7 @@ _complete_help() {
 
     ${1:-_main_complete}
   } always {
-    unfunction compadd compcall zstyle
+    _unshadow compadd compcall zstyle
   }
 
   for i in "${(@ok)help_funcs}"; do