rbenv版本在zsh右提示中显示不刷新

3

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

我在RPS1提示符中有以下代码:

RPS1='${PR_GREEN}$(virtualenv_info)%{$reset_color%} ${PR_RED}${ruby_version}%{$reset_color%}'
< p >(为简洁起见,未显示设置PR_颜色或确定虚拟环境的代码 - 两者都有效。) < p >当创建新的shell(在iTerm2中的新窗口或新选项卡中)时,Ruby信息是正确的。但是,如果我切换到使用不同Ruby的项目(由 < code > .ruby-version 文件确定),则右提示显示的Ruby信息不会刷新。如果我重新加载我的 .zshrc 文件,右提示将被刷新。 < p >我需要将确定Ruby版本的代码包含在函数中吗?顺便说一下,我的 .zshrc 中也有 setopt promptsubst。 < p >我缺少什么阻止右提示在更改目录时刷新?

如果我用单引号包围$(rbenv version | see -e "s/ (set.$//")这行代码,那么我就可以在我的右提示符中看到该字符串。当该行被双引号包围时,如原始问题所示,只有在加载~/.zshrc后才能看到当前的Ruby版本。 - Mark Nichols
3个回答

5

您不应该使用这段代码

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

在zshrc中直接设置ruby_version变量,当切换到另一个项目时,它不会更新。您可以将其更改为:

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
}

将提示符中的${ruby_version}更改为$(ruby_version)。或者,如果您确定不需要在每个提示符上检查它(这会减慢速度),则可以使用

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)

它仅在您更改当前目录时更新ruby_version。另请注意,您的代码会导致误解:local ruby_version ='' 相当于 typeset -g ruby_version ='' 或者只是简单的 ruby_version =''。这将定义全局变量,但不是导出变量。在zsh中没有文件本地变量(除了实际代表函数的autoload文件)。


这两种变化都完美地工作了。谢谢。我已经实现了其中的第二种,使用 chpwd_functions 行仅在目录更改时测试 Ruby 版本。唯一可能出现问题的情况是设置具有本地 Ruby 的新项目。在发出 rbenv local 命令定义该 Ruby 后,我必须离开 pwd 并返回以重置提示符 - 这只是一个小细节。再次感谢。 - Mark Nichols
@MarkNichols 您不需要两次更改目录。只需使用 cd .:它会触发“chpwd”钩子,但实际上并不更改目录。 - ZyX
你不需要运行sed。rbenv有一个仅用于版本的命令。只需输入rbenv version-name,您将仅获取您要查找的版本。 - Fa11enAngel
@Fa11enAngel 我的系统上没有安装rbenv,而且我对Ruby开发几乎一无所知,只是从问题中复制了代码。不会编辑帖子,因为OP使用sed可能有原因:即旧版本的rbenv不支持version-name - ZyX

1
使用这个:
export ruby_version
if
  which rvm-prompt &> /dev/null
then
  ruby_version='$(rvm-prompt i v g)'
elif
  which rbenv &> /dev/null
then
  ruby_version='$(rbenv version | sed -e "s/ (set.*$//")'
else
  ruby_version=''
fi

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

这将把ruby_version变量代码注入到RPS1中。

使用上述代码,我的 RPROMPT 显示单引号内的文本。如下所示:$(rbenv version | sed -e "s/ (set.*$//") 将单引号更改为双引号将使我回到最初不正确的行为。 - Mark Nichols

0

看起来你需要使用 precmd 钩子,它在每次执行命令时都会被执行,比如切换文件夹。与你之前的方式不同,那种方式只在启动新实例时执行一次。

precmd () {

  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

  #you can use RPROMPT
  RPS1='${PR_GREEN}$(virtualenv_info)%{$reset_color%} ${PR_RED}${ruby_version}%{$reset_color%}'
}

请确保不要覆盖此函数,仅在其他地方未创建时才创建它。因为很可能已经在您的.zshrc或其他与zsh相关的文件中定义了它,特别是如果您正在使用像oh-my-zsh这样的东西,或者其他显示git(或其他版本控制)信息的提示符之类的东西。

更多相关信息


在验证我的zsh配置中没有其他precmd之后,我使用precmd包装了RPROMPT。我以前使用的是on-my-zsh,但发现它很慢,因此现在我正在自己配置。 RPROMPT的行为没有改变。我需要继续阅读zsh手册。 - Mark Nichols

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接