From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh Users <zsh-users@zsh.org>
Subject: Things you can do with mkshadow
Date: Sun, 10 Sep 2023 11:21:40 -0700 [thread overview]
Message-ID: <CAH+w=7Y5nbW6rj=vj_84Xsnex=upE=PEybYBxA0t=LJuBSV0Hg@mail.gmail.com> (raw)
I'm not really sure where else to put this, so putting it here.
Briefly, the mkshadow utility creates a "shadow copy" of a function,
builtin, or command so that it can be locally redefined. (Anything
not a function or builtin is presumed to be a command.) The canonical
usage is something like
hello() { print Hello, world }
greeting() { hello }
howdy() {
{ mkshadow hello
hello() { print Howdy, pardner }
greeting
} always {
rmshadow
}
}
Calling rmshadow undoes everything back to the most recent call to
mkshadow, so the use of an "always" block is a good way to assure the
two are called in matching pairs. However, this isn't required. For
example, the local redefinition can unmask itself:
howdy() {
{ mkshadow hello
hello() {
print Howdy, pardner
{ rmshadow
greeting
} always {
mkshadow hello
}
}
greeting
} always {
rmshadow
}
}
This makes the internal redefinition of "hello" behave like a
locally-scoped function. Whenever it's called from "howdy" it removes
the shadow copy so that anything it might call sees the original
definition of "hello". It then restores the shadow so that "howdy"
can safely remove it again.
There's an extra nuance available, which is that mkshadow can be told
how to name the shadow copy.
howdy() {
{ mkshadow -s howdy hello
hello() { print Howdy, pardner }
greeting
} always {
rmshadow
}
}
Without the -s option, a new shadow copy is created on every call, so
for example in recursive functions you can end up with shadows of
shadows. With -s, a new copy is created only on the first call, but
the number of mkshadow calls is still remembered, so rmshadow will not
restore the original function until the full stack is unwound. This
is most useful when the redefined function wants to call the original
-- note how the shadow name is appended to the original name to create
the new function:
howdy() {
{ mkshadow -s howdy hello
hello() {
print Howdy, pardner
hello@howdy
}
greeting
} always {
rmshadow
}
}
Even without -s you can access the most-recently shadowed function by
capturing the value of $REPLY following the call to mkshadow.
howdy() {
{ mkshadow hello
local hellofn="hello@$REPLY"
hello() {
print Howdy, pardner
$hellofn
}
greeting
} always {
rmshadow
}
}
As a final hint, rmshadow also sets $REPLY to the name set by the most
recent mkshadow, which is handy for the locally-scoped function trick.
howdy() {
{ mkshadow -s howdy hello
hello() {
print Howdy, pardner
{ rmshadow
local shadow=$REPLY
greeting
} always {
mkshadow -s $shadow hello
}
}
greeting
} always {
rmshadow
}
}
For those not on zsh-workers, mkshadow can be found here:
https://raw.githubusercontent.com/zsh-users/zsh/master/Functions/Misc/mkshadow
https://raw.githubusercontent.com/zsh-users/zsh/master/Completion/Base/Utility/_shadow
It uses a new feature developed in March - June 2023, so to make it
compatible with current released versions as of this posting, run
sed -e 's/\.shadow\./_shadow_/g' < _shadow > _shadow-5_9
mv _shadow-5_9 _shadow
reply other threads:[~2023-09-10 18:23 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=7Y5nbW6rj=vj_84Xsnex=upE=PEybYBxA0t=LJuBSV0Hg@mail.gmail.com' \
--to=schaefer@brasslantern.com \
--cc=zsh-users@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).