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 | |
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')
-rw-r--r-- | Completion/Base/Utility/_shadow | 71 | ||||
-rw-r--r-- | Completion/Base/Widget/_complete_help | 3 |
2 files changed, 73 insertions, 1 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 "$@" 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 |