about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2023-08-27 15:22:14 -0700
committerBart Schaefer <schaefer@zsh.org>2023-08-27 15:22:14 -0700
commit2a854aae481e7eb064729db28a71ed0efb2f33e6 (patch)
treee14cf07882b51c5416944eb49f847524046e6d79 /Completion
parent97b4a30c4e5f4837bac7c5c67bd583d3aeaf7886 (diff)
downloadzsh-2a854aae481e7eb064729db28a71ed0efb2f33e6.tar.gz
zsh-2a854aae481e7eb064729db28a71ed0efb2f33e6.tar.xz
zsh-2a854aae481e7eb064729db28a71ed0efb2f33e6.zip
52028: improvements to _shadow / _unshadow, plus helper and doc
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/Utility/_shadow66
1 files changed, 46 insertions, 20 deletions
diff --git a/Completion/Base/Utility/_shadow b/Completion/Base/Utility/_shadow
index 5b0f79c36..b5a8acb24 100644
--- a/Completion/Base/Utility/_shadow
+++ b/Completion/Base/Utility/_shadow
@@ -8,7 +8,7 @@
 #    }
 #    # Invoke callers of fname
 #  } always {
-#    _unshadow fname
+#    _unshadow
 #  }
 ## Alternate usage:
 # {
@@ -19,7 +19,7 @@
 #   }
 #   # Invoke callers of fname
 # } always {
-#   _unshadow -s suffix fname
+#   _unshadow
 # }
 ##
 
@@ -33,36 +33,62 @@ 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.
-typeset -gHi _shadowdepth=0
+builtin typeset -gHi .shadow.depth=0
+builtin typeset -gHa .shadow.stack
 
 # Create a copy of each fname so that a caller may redefine
 _shadow() {
-  local -A fsfx=( -s ${funcstack[2]}:${functrace[2]}:$((_shadowdepth+1)) )
-  local fname
+  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
-    local shadowname=${fname}@${fsfx[-s]}
-    (( ${+functions[$fname]} )) &&
-      builtin functions -c $fname $shadowname
+    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 -- $shadowname { builtin $fname \"\$@\" }"
+      fnames+=(b@$fname)
+    else
+      eval "function -- $shadowname { command $fname \"\$@\" }"
+      fnames+=(c@$fname)
+    fi
   done
-  ((_shadowdepth++))
+  [[ -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() {
-  local -A fsfx=( -s ${funcstack[2]}:${functrace[2]}:${_shadowdepth} )
-  local fname
-  zparseopts -K -A fsfx -D s:
-  for fname; do
-    local shadowname=${fname}@${fsfx[-s]}
-    if (( ${+functions[$shadowname]} )); then
-      builtin functions -c $shadowname $fname
-      builtin unfunction $shadowname
-    elif (( ${+functions[$fname]} )); then
-      builtin unfunction $fname
+  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
-  ((_shadowdepth--))
+  [[ -z $REPLY ]] && REPLY=$fsfx
+  shift .shadow.stack
+  ((.shadow.depth--))
 }
 
 # This is tricky.  When we call _shadow recursively from autoload,