zsh-users
 help / color / mirror / code / Atom feed
* Things you can do with mkshadow
@ 2023-09-10 18:21 Bart Schaefer
  0 siblings, 0 replies; only message in thread
From: Bart Schaefer @ 2023-09-10 18:21 UTC (permalink / raw)
  To: Zsh Users

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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-09-10 18:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-10 18:21 Things you can do with mkshadow Bart Schaefer

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).