1

Suppose, for example, that fpath is set to

( $HOME/.zsh/my-functions /usr/local/share/zsh/site-functions )

...and that both function-defining files $HOME/.zsh/my-functions/quux and /usr/local/share/zsh/site-functions/quux exist.

(I'll refer to these two versions of quux as "the user's quux" and "the site's quux", respectively.)

Furthermore, let's assume that I've run

autoload -U quux

This means that, if I now run quux, the one that will be run is the user's quux.

The word "overrides" in this post title refers to the fact that, in such a situation, the user's quux "overrides" the site's quux. (I could have "shadows" instead of "overrides".)


My question is: is there a way for the user's quux to, in turn, invoke the site's quux? (In a typical scenario, the user's quux would massage the arguments passed to the site's quux, and/or massage the output produced by it.)

I'm looking for solutions that do not require modifying anything under /usr/local/share/zsh/site-functions/quux.

IMPORTANT: The fpath used in this question is just an example. In general, all we know is that one function reachable through fpath overrides (shadows) some other such function.


I've experimented with dastardly schemes where, e.g., $HOME/.zsh/my-functions/quux takes the general form

# one-time initialization
local body
body=$( SOMEHOW <???> GET SOURCE CODE OF OVERRIDDEN FUNCTION )
eval "overridden_quux () {
$body
}"

# self-re-definition (MWAH-HA-HA-HA-HAAAA!)
quux () {
    local massaged_args
    massaged_args=( $( MASSAGE ARGS "$@" ) )
    __overridden_quux "$massaged_args" | MASSAGE OUTPUT
}

# one-time re-invocation
quux "$@"

...but the results are very fragile, to say nothing of the ugliness of the approach.

4

The easy way is to force the loading of the original function, rename it, and redefine it in your .zshrc, rather than having a function with the same name in your fpath. Note that in zsh, you don't need complex tricks involving which, eval and wondering about quoting to rename a function: simply use the functions associative array.

autoload -Uz +X quux
functions[overridden_quux]=$functions[quux]
quux () {
  … overridden_quux $@[@] …
}

If you want the function to be autoloaded from a file in fpath, it gets fiddly because you need to load the original without accessing the same fpath entry recursively. I don't have a better solution to propose than locally redefining fpath.

#autoload quux
functions[overridden_quux]=$(
    fpath=("${(@)fpath:#$HOME/*}")
    autoload -Uz +x quux
    print -r -- $functions[quux]
)
quux () {
  … overridden_quux $@[@] …
}
  • I had the strong suspicion that I was overcomplicating things, and you just proved it. Beautiful answer. Thanks. – kjo Jan 16 '17 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.