diff options
author | Bart Schaefer <schaefer@zsh.org> | 2022-06-04 14:19:42 -0700 |
---|---|---|
committer | Bart Schaefer <schaefer@zsh.org> | 2022-06-04 14:19:42 -0700 |
commit | a99f96797f5fc424554a94313dfc0d4a5b0923a1 (patch) | |
tree | 5cb7d78e59fb24c5ae8ab5f2c1579da279df73b8 /Completion/Base/Utility/_shadow | |
parent | 3e3cfabcc74dc79d4d8717c4e5859d8d01be6c54 (diff) | |
download | zsh-a99f96797f5fc424554a94313dfc0d4a5b0923a1.tar.gz zsh-a99f96797f5fc424554a94313dfc0d4a5b0923a1.tar.xz zsh-a99f96797f5fc424554a94313dfc0d4a5b0923a1.zip |
50323: create helper for shadowing builtins or existing functions and use it when redefining compadd et al.
Diffstat (limited to 'Completion/Base/Utility/_shadow')
-rw-r--r-- | Completion/Base/Utility/_shadow | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/Completion/Base/Utility/_shadow b/Completion/Base/Utility/_shadow new file mode 100644 index 000000000..5b0f79c36 --- /dev/null +++ b/Completion/Base/Utility/_shadow @@ -0,0 +1,71 @@ +#autoload + +## Recommended usage: +# { +# _shadow fname +# function fname { +# # Do your new thing +# } +# # Invoke callers of fname +# } always { +# _unshadow fname +# } +## Alternate usage: +# { +# _shadow -s suffix fname +# function fname { +# # Do other stuff +# fname@suffix new args for fname +# } +# # Invoke callers of fname +# } always { +# _unshadow -s suffix fname +# } +## + +# 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. +typeset -gHi _shadowdepth=0 + +# 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 + zparseopts -K -A fsfx -D s: + for fname; do + local shadowname=${fname}@${fsfx[-s]} + (( ${+functions[$fname]} )) && + builtin functions -c $fname $shadowname + done + ((_shadowdepth++)) +} + +# 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 + fi + done + ((_shadowdepth--)) +} + +# 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 "$@" |