Scripting

函式如何呼叫它“覆蓋”的函式?

  • January 16, 2017

例如,假設fpath設置為

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

…並且功能定義文件都$HOME/.zsh/my-functions/quux存在/usr/local/share/zsh/site-functions/quux

(我將這兩個版本分別quux稱為“使用者的quux”和“站點的quux”。)

此外,讓我們假設我已經跑了

autoload -U quux

這意味著,如果我現在執行quux,將執行的是使用者的quux.

這篇文章標題中的“覆蓋”一詞是指在這種情況下,使用者的quux“覆蓋”網站的quux. (我可以有“陰影”而不是“覆蓋”。)


我的問題是:有沒有辦法讓使用者quux反過來呼叫網站的quux?(在典型的場景中,使用者quux會按摩傳遞給站點的參數quux,和/或按摩它產生的輸出。)

我正在尋找不需要在/usr/local/share/zsh/site-functions/quux.

重要提示:fpath此問題中使用的只是一個範例。一般來說,我們所知道的是一個函式可以通過fpath覆蓋(陰影)其他一些這樣的函式來訪問。


我已經嘗試了一些卑鄙的方案,例如,$HOME/.zsh/my-functions/quux採用一般形式

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

…但結果非常脆弱,更不用說這種方法的醜陋了。

簡單的方法是強制載入原始函式,重命名它,然後在.zshrc你的 . 請注意,在 zsh 中,您不需要涉及 的複雜技巧which,也不需要eval考慮引用來重命名函式:只需使用functions關聯數組即可。

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

如果您希望從 fpath 中的文件自動載入函式,它會變得很繁瑣,因為您需要載入原始文件而不遞歸地訪問相同的 fpath 條目。我沒有比本地重新定義更好的解決方案fpath

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

引用自:https://unix.stackexchange.com/questions/337594