From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Shadowing builtins and functions
Date: Thu, 2 Jun 2022 18:36:52 -0700 [thread overview]
Message-ID: <CAH+w=7Y+hv5JkkdgmBr9wOr1zE8Ud4U6mevRGuBqrem6AArw4A@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1922 bytes --]
In workers 50316, I wrote:
> That needs some work to avoid conflicting with other helpers that
> redefine compadd
As far as I can tell that now means only _complete_help and
_approximate, and _approximate already avoids redefining compadd when
it is a function instead of a builtin. I'm not sure if that affects
the results of _complete_help for contexts that use _approximate.
Nevertheless it seems as though a helper for temporarily redefining
builtins and functions as new functions is possible, so an attempt at
it is attached. The idea here is to create a new unique function name
and link it to the original function, which preserves the function
body, and then unwind that when the redefined function is not needed.
There's no neat way to do this without help from the caller in the
form of an "always" block.
So after a bit of noodling with that idea, the result is _shadow
(attached as _shadow.txt for list server compatibility). Example of
usage:
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
I'm not certain that Completion/Base/Utility is where _shadow would
best be committed, but currently the only places we might want it are
in completion, so it should be loaded along with completions, so
that's where I was thinking to put it.
Remarks?
[-- Attachment #2: _shadow.txt --]
[-- Type: text/plain, Size: 1935 bytes --]
#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 "$@"
next reply other threads:[~2022-06-03 1:37 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-03 1:36 Bart Schaefer [this message]
2022-06-04 21:22 ` Bart Schaefer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAH+w=7Y+hv5JkkdgmBr9wOr1zE8Ud4U6mevRGuBqrem6AArw4A@mail.gmail.com' \
--to=schaefer@brasslantern.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).