在带有 prompinit 的 zsh 自定义提示符中使用 vcs_info

Using vcs_info in zsh custom prompt with promptinit

目前在我的 .zshrc 中,我有以下行来提供一些 git 信息:

autoload -Uz vcs_info
precmd_vcs_info() { vcs_info }
precmd_functions+=( precmd_vcs_info )
setopt prompt_subst
RPROMPT=$vcs_info_msg_0_
zstyle ':vcs_info:git:*' formats '%b'

这使我的 shell 看起来像下面这样:

[me@computer dir]$                                                                  main

我想将此配置移出 .zshrc 并移至使用 promptinit 初始化的自定义提示中。此配置位于我的 fpath 上可用的名为 prompt_mycustomprompt_setup 的文件中。配置如下所示:

precmd_vcs_info() {
    vcs_info
}

prompt_mycustomprompt_setup () {
    autoload -Uz add-zsh-hook vcs_info
    setopt prompt_subst
    add-zsh-hook precmd precmd_vcs_info
    RPROMPT=$vcs_info_msg_0_
    zstyle ':vcs_info:git:*' formats '%b'

    PS1='(test)> '
}

prompt_mycustomprompt_setup "$@"

然后我从 .zshrc 中删除了相关行并替换为以下行:

autoload -Uz promptinit
promptinit

prompt mycustomprompt

但是,vcs_info 没有显示,而是我的提示中有一个常量静态值 $vcs_info_msg_0_

(test)>                                                         $vcs_info_msg_0_

为什么我的提示不按预期运行?

发生这种情况是因为函数中的语句 setopt promptsubst 是在 prompt 函数内部执行的,该函数执行 setopt localoptions。因此,当 prompt returns 时,该选项将重置为默认值。

不是直接设置 shell 选项,promptinit 主题应该 set the prompt_opts array:

The array prompt_opts may be assigned any of "bang", "cr", "percent", "sp", and/or "subst" as values. The corresponding setopts (promptbang, etc.) are turned on, all other prompt-related options are turned off.

因此,为了提示您使用 setopt promptsubst,您应该在 setup 函数中执行如下操作:

prompt_opts=(cr percent sp subst)

然而,正如 Zsh mailing list 中提到的,Zsh 开发者通常建议 不要 使用 promptsubst,因为这可以

  • 有您可能意想不到的副作用(例如使用 print -P 时)and/or
  • 导致性能不佳(当提示中的表达式结果比预期的更昂贵并且在重绘提示时重新评估)。

为确保最佳性能和稳定性,我建议改为这样做:

prompt_mycustomprompt_precmd() {
    vcs_info
    RPS1=" $vcs_info_msg_0_"
}

prompt_mycustomprompt_setup () {
    autoload -Uz vcs_info
    add-zsh-hook precmd prompt_mycustomprompt_precmd   
    zstyle ':vcs_info:git:*' formats '%b'

    prompt_opts=( cr percent sp )
    PS1='(test)> '
}

prompt_mycustomprompt_setup "$@"

请注意,我还重命名了您的 precmd 钩子函数,因为所有 prompinit 钩子函数名称都应该遵循模式 prompt_<theme>_<hook>,因此 the prompt function can automatically unhook them 当切换主题。

此外,promptinit 主题应该使用较短的 $PS1$RPS1 等,而不是 $PROMPT$RPROMPT