Como uma função pode chamar a função que ela “substitui”?

1

Suponha, por exemplo, que fpath esteja definido como

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

... e que ambos os arquivos de definição de função $HOME/.zsh/my-functions/quux e /usr/local/share/zsh/site-functions/quux existem.

(Vou me referir a essas duas versões de quux como "o usuário quux " e "o site quux ", respectivamente).

Além disso, vamos supor que eu corri

autoload -U quux

Isso significa que, se eu executar quux , o que será executado será o quux do usuário.

A palavra "substituições" neste título de postagem refere-se ao fato de que, em tal situação, o usuário quux "substitui" o site quux . (Eu poderia ter "sombras" em vez de "overrides".)

Minha pergunta é: existe uma maneira de o usuário quux , por sua vez, invocar o site quux ? (Em um cenário típico, o usuário quux massagearia os argumentos passados para o site quux e / ou massagearia a saída produzida por ele.)

Estou procurando soluções que não requeiram nada em /usr/local/share/zsh/site-functions/quux .

IMPORTANTE: O fpath usado nesta questão é apenas um exemplo . Em geral, tudo o que sabemos é que uma função alcançável através de fpath substitui (sombras) alguma outra função.

Eu experimentei esquemas inoportunos onde, por exemplo, $HOME/.zsh/my-functions/quux assume a forma geral

# 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 "$@"

... mas os resultados são muito frágeis, para não falar da feiura da abordagem.

    
por kjo 15.01.2017 / 18:03

1 resposta

4

A maneira mais fácil é forçar o carregamento da função original, renomeá-la e redefini-la no seu .zshrc , em vez de ter uma função com o mesmo nome no seu fpath. Note que em zsh, você não precisa de truques complexos envolvendo which , eval e querendo saber como citar para renomear uma função: simplesmente use o functions array associativo .

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

Se você quiser que a função seja carregada automaticamente a partir de um arquivo no fpath, ela fica complicada porque você precisa carregar o original sem acessar a mesma entrada de fpath recursivamente. Eu não tenho uma solução melhor para propor do que localmente redefinindo fpath .

#autoload quux
functions[overridden_quux]=$(
    fpath=("${(@)fpath:#$HOME/*}")
    autoload -Uz +x quux
    print -r -- $functions[quux]
)
quux () {
  … overridden_quux $@[@] …
}
    
por 16.01.2017 / 00:24