Nauxk
Nauxk

Reputation: 25

Using vcs_info in zsh custom prompt with promptinit

Currently in my .zshrc I have the following lines to provide some git info:

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'

This makes my shell look like the following:

[me@computer dir]$                                                                  main

I would like to move this configuration out of .zshrc and into a custom prompt that is initiliazed using promptinit. This configuration is in a file called prompt_mycustomprompt_setup that is available on my fpath. The configuration looks as follows:

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

I then removed the relevant lines from my .zshrc and replaced with the following lines:

autoload -Uz promptinit
promptinit

prompt mycustomprompt

However, the vcs_info is not displayed and instead I have a constant static value of $vcs_info_msg_0_ in my prompt:

(test)>                                                         $vcs_info_msg_0_

Why will my prompt not behave as expected?

Upvotes: 2

Views: 1617

Answers (1)

Marlon Richert
Marlon Richert

Reputation: 7020

That happens because the statement setopt promptsubst in your function is executed inside the prompt function, which does setopt localoptions. So, when prompt returns, the option gets reset to default.

Instead of setting shell options directly, promptinit themes are supposed to 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.

So, for your prompt to use setopt promptsubst, you should do something like this in your setup function:

prompt_opts=(cr percent sp subst)

However, as mentioned on the Zsh mailing list, the Zsh devs generally recommend not to use promptsubst, as this can

  • have side effects where you might not expect them (such as when using print -P) and/or
  • result in poor performance (when an expression in your prompt turns out to be more expensive than expected and gets re-evaluated whenever the prompt gets redrawn).

To ensure optimal performance and stability, I would recommend doing this instead:

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

Note that I have also renamed your precmd hook function, because all prompinit hook function names are supposed to follow the pattern prompt_<theme>_<hook>, so that the prompt function can automatically unhook them when switching themes.

Additionally, promptinit themes are supposed to use the shorter $PS1, $RPS1, etc. instead of $PROMPT, $RPROMPT, etc.

Upvotes: 3

Related Questions