何时需要在 zsh 小部件调用的函数中包含“emulate -LR zsh”?

何时需要在 zsh 小部件调用的函数中包含“emulate -LR zsh”?

我已在我的~/.zshrc以下代码中包含:

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z

...我在一个回答对这个问题在检查某些内容时记住半输入的命令

它有效,但最初的代码包含以下语句:

emulate -LR zsh

我寻找emulate里面的命令man zshbuiltins来理解-L-R选项。

似乎emulate -R zsh将所有选项重置为其默认值,我用以下命令检查了这一点:

vimdiff <(setopt) <(emulate -R zsh; setopt)

但是,如果我emulate -R zsh在交互式 shell 中执行,它会明确重置选项,因此我认为这就是-L需要该标志的地方:
使选项的新值成为当前函数的本地选项(如果有)。

这似乎还意味着,除了全局选项之外,选项还可以具有本地值,并且在发生冲突的情况下,本地选项具有优先权。

因此,emulate -LR zsh用于重新创建一个具有默认值和可预测选项值的本地环境,其中小部件的作者不必想知道调用其函数时选项是什么,或者保存(在函数的开头)然后恢复(在最后)所有可能改变小部件预期行为的选项。

我没有复制该行,因为它似乎没有它就可以工作。但是,我想知道我对这个命令的理解是否正确,是否有人可以提供一两个简单的例子,哪些地方emulate -LR zsh需要避免副作用。

答案1

你的理解是正确的。

emulate -R zsh将所有选项重置为 zsh 默认值。该-L标志使 this 成为包含函数的本地变量(更一般地,使所有选项更改成为该函数的本地变量)。

emulate -LR zsh当函数要在选项可能不同的上下文中使用时(尤其是在交互式 shell 中),将函数定义放在靠近开头的位置是一种良好的卫生习惯。

在这个特定的实例中,emulate -LR zsh不需要,因为代码不受任何选项的影响。但它没有任何害处。

以下是用户可以在初始化文件中设置的选项的一些示例,或者可以通过调用该函数的周围代码禁用这些选项,并且可能会破坏函数:

  • 关闭bare_glob_qual破坏了 glob 限定符的使用。
  • 关闭care_glob或者case_match将使某些模式匹配不区分大小写,即使它在函数中可能没有意义。
  • null_globcsh_null_glob影响不匹配任何文件的 glob 模式的行为。
  • numeric_glob_sort可以破坏需要按字典顺序扩展模式的功能。
  • err_exitunset当函数的代码打算执行默认行为时,可能会导致错误(忽略命令的状态,将未定义的变量视为空)。

相关内容