Search code examples
rvmzshrbenvzshrc

rbenv version display in zsh right-prompt not refreshing


I have the following code in my .zshrc:

local ruby_version=''
if which rvm-prompt &> /dev/null; then
  ruby_version="$(rvm-prompt i v g)"
else
  if which rbenv &> /dev/null; then
    ruby_version="$(rbenv version | sed -e "s/ (set.*$//")"
  fi
fi

And I have this code in my RPS1 prompt:

RPS1='${PR_GREEN}$(virtualenv_info)%{$reset_color%} ${PR_RED}${ruby_version}%{$reset_color%}'

(For brevity sake I have not shown the code that sets the PR_ colors or determines the virtual environment - both of those work.)

When a new shell is created (new window or new tab in iTerm2) the Ruby information is correct. However if I switch to a project that uses a different Ruby, as determined by the .ruby-version file, the Ruby information displayed in the right prompt does not refresh. If I re-source my .zshrc file the right-prompt does refresh.

Do I need to encase the code that determines the Ruby version in a function? By the way, I do have setopt promptsubst in my .zshrc as well.

What am I missing that is preventing the right-prompt from refreshing when I change directories?


Solution

  • You should not be using this code

    local ruby_version=''
    if which rvm-prompt &> /dev/null; then
      ruby_version="$(rvm-prompt i v g)"
    else
      if which rbenv &> /dev/null; then
        ruby_version="$(rbenv version | sed -e "s/ (set.*$//")"
      fi
    fi
    

    directly in zshrc: it won’t update ruby_version variable when switching to another project. You can change it to

    function ruby_version()
    {
        if which rvm-prompt &> /dev/null; then
          rvm-prompt i v g
        else
          if which rbenv &> /dev/null; then
            rbenv version | sed -e "s/ (set.*$//"
          fi
        fi
    }
    

    and change ${ruby_version} in your prompt to $(ruby_version). Or, if you are sure you don’t need checking this on each prompt (it will slow things down) you can use

    function _update_ruby_version()
    {
        typeset -g ruby_version=''
        if which rvm-prompt &> /dev/null; then
          ruby_version="$(rvm-prompt i v g)"
          rvm-prompt i v g
        else
          if which rbenv &> /dev/null; then
            ruby_version="$(rbenv version | sed -e "s/ (set.*$//")"
          fi
        fi
    }
    chpwd_functions+=(_update_ruby_version)
    

    , it will update ruby_version only when you change current directory. Also note that your code is misleading: local ruby_version='' that is put directly into zshrc is equivalent to typeset -g ruby_version='' or just plain ruby_version='' which defines global, but not exported variable. There are no file-local variables in zsh (except for autoload files that actually represent functions).