Bash $PROMPT_COMMAND 搞乱滚动历史显示

Bash $PROMPT_COMMAND 搞乱滚动历史显示

我设置了一个PROMPT_COMMAND来在 git 存储库中显示当前分支。

我的 .bashrc 的相关部分是:

export PS1=" \[\033[34m\]\$\[\033[0m\] "
export PROMPT_COMMAND="$HOME/bin/myprompt"

其中 ~/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

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

~ $ pwd
/Users/Adrian
~ $ cd sibilant
~/sibilant (master) $ pwd
/Users/Adrian/sibilant
~/sibilant (master) $

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

~/sibilant (master) $ pwd
~/sibilant (master) $ cd sibilant
~/spwd

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

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

答案1

不要放入PROMPT_COMMAND,而是放入PS1

PS1='$($HOME/bin/myprompt) \[\033[34m\]\$\[\033[0m\] '

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

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

答案2

PROMPT_COMMAND 可以包含在 bash 打印新提示符之前执行的命令(即在评估 PS1 之前)。

在 git 1.8.1 中,发布了使用 PROMPT_COMMAND 有效执行此操作的代码。看将 git-prompt.sh 与 PROMPT_COMMAND 一起使用。该代码可以与早期版本的 git 一起使用,只需将文件 contrib/completion/git-prompt.sh 复制到可以从 .bashrc 获取它的位置。

干杯

西蒙

相关内容