Shell

zsh 有類似閉包的東西嗎?

  • June 25, 2020

我剛剛決定嘗試 zsh(通過 oh-my-zsh),現在正在precmd模擬一個兩行提示,其中包含正確提示,而不僅僅是最後一行。

所以我複製了預設主題,並受到這篇文章的啟發(我也用它來學習很多東西),我做了這樣的事情(我稍後會添加顏色):

function precmd {
   local cwd="${(%):-[%~]}"
   local who_where="${(%):-%n@%m}"
   local git_info=${(%)$(git_prompt_info)}
   local right_prompt="     $git_info [$who_where]"
   local left_prompt="${(r:(($COLUMNS - ${#${right_prompt}})):: :)cwd}"

   echo "$left_prompt$right_prompt"
}

它有效。但我不禁想知道:zsh 是否在每次呼叫 precmd 時都定義了所有這些變數?

我一直在搜尋與 zsh 相關的閉包、範圍和命名空間,希望將本地變數作為數據附加到 precmd,因此不需要每次都重新定義變數,但我什麼也沒找到。有什麼方法可以做我正在嘗試的事情,還是應該放棄它?

作為旁注,並且僅當它相關時,“載入函式”是什麼意思?

Zsh 沒有閉包、包或命名空間之類的東西。Zsh 缺少真正的閉包所需的一堆東西:

  • 函式不是一流的。您不能將函式作為參數傳遞給其他函式,函式也不能返回其他函式。(您可以傳遞要呼叫的函式的名稱,但這與傳遞函式本身不同)。
  • 你不能有嵌套函式。zsh 中的所有函式都是全域的。您必須為函式名稱添加前綴以避免衝突。請特別注意,函式將隱藏同名的外部程序。如果你有一個函式被呼叫ls,它將被呼叫而不是程序ls。這可能很有用,除非您不小心這樣做。
  • 變數是動態範圍的,而不是像大多數現代語言那樣是靜態範圍的。即使您可以擁有嵌套函式,內部函式也不會以您通常期望的方式關閉外部函式的局部變數。你不能用它們來製作模組,就像人們在 Javascript 中所做的那樣。
  • Zsh確實有匿名函式,但沒有任何這些其他東西,它們並沒有多大用處。

所以基本上,你能做的最好的就是給你所有的函式和全域變數加上前綴。

我還要指出,你應該precmd像這樣定義你的:

% autoload -Uz add-zsh-hook
% add-zsh-hook precmd my_precmd_function

add-zsh-hook讓您可以將您的函式掛接到precmd其中,而不會覆蓋任何其他可能也想掛接的函式precmd

載入函式意味著什麼是一個單獨的問題。Zsh 具有自動載入功能,僅在實際呼叫函式時才從磁碟載入函式。當你這樣做時autoload -Uz foobar,這使得名為的函式foobar可以呼叫。當您實際呼叫foobar時,它會從磁碟載入定義。

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