Bash $PROMPT_COMMAND 弄乱了滚动历史显示

adr*_*usi 7 bash prompt

PROMPT_COMMAND当我在 git repo 中时,我设置了一个来显示当前分支。

我的 .bashrc 的相关部分是:

export PS1=" \[\033[34m\]\$\[\033[0m\] "
export PROMPT_COMMAND="$HOME/bin/myprompt"
Run Code Online (Sandbox Code Playgroud)

其中 ~/bin/myprompt 是:

#!/usr/bin/env ruby
green = "\033[32m"
bold = "\033[1m"
underline = "\033[4m"
reset = "\033[0m"

home_regex = Regexp.new "^#{ENV["HOME"]}"
Dir.chdir ENV["PWD"]

out = 
  underline + bold + green +
  `pwd`.gsub(home_regex, "~").chomp +
  reset

if `git log 2>&1 | grep ^fatal`.chomp == ""
  out += "#{underline}#{green} (#{`git branch | grep ^\* | sed s/^..//g`.chomp})#{reset}"
end

print out
Run Code Online (Sandbox Code Playgroud)

在大多数情况下它工作正常,唯一的问题是当我使用箭头键滚动命令历史时,有时命令会写在我的提示上。假设有以下会话:

~ $ pwd
/Users/Adrian
~ $ cd sibilant
~/sibilant (master) $ pwd
/Users/Adrian/sibilant
~/sibilant (master) $
Run Code Online (Sandbox Code Playgroud)

然后我按向上箭头滚动命令历史记录。每行显示按一次箭头的结果:

~/sibilant (master) $ pwd
~/sibilant (master) $ cd sibilant
~/spwd
Run Code Online (Sandbox Code Playgroud)

如您所见,上次我按下箭头时,命令写在我的提示上。

有没有人经历过这个和/或知道如何解决它?

Ric*_*sen 11

而不是把它PROMPT_COMMAND放进去,把它放进去PS1

PS1='$($HOME/bin/myprompt) \[\033[34m\]\$\[\033[0m\] '
Run Code Online (Sandbox Code Playgroud)

当它在 中时PS1,bash 会计算打印的字符数,以便在您滚动历史记录时可以正确重绘。这就是 bash 具有\[\]特殊字符的原因——它们告诉 bash 封闭的字符不可打印,这有助于 bash 确定如何在必要时重绘提示。

请注意,命令替换位于单引号内。这可以防止在分配时扩展。如果命令替换是在双引号中或不带引号的,则 的输出myprompt将在赋值时捕获一次并保持静态。为了支持随时间变化的变量值,PS1每次显示提示时,shell 都会扩展 的值。这意味着在赋值时应该通过引用来防止扩展。这也意味着您需要注意速度:如果命令替换需要 1 秒才能完成,那么您的提示将需要 1 秒才能显示。