I set up a PROMPT_COMMAND
to display the current branch while I'm in a git repo.
The relevant part of my .bashrc is:
export PS1=" \[\033[34m\]\$\[\033[0m\] "
export PROMPT_COMMAND="$HOME/bin/myprompt"
where ~/bin/myprompt is:
#!/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
It works fine for the most part, the only problem is that when I use the arrow keys to scroll through command history, sometimes the command gets written over my prompt. Suppose the following session:
~ $ pwd
/Users/Adrian
~ $ cd sibilant
~/sibilant (master) $ pwd
/Users/Adrian/sibilant
~/sibilant (master) $
Then I press the up arrow to scroll through command history. each line shows the result of one press of the arrow:
~/sibilant (master) $ pwd
~/sibilant (master) $ cd sibilant
~/spwd
as you can see, the last time I pressed the arrow the command was written over my prompt.
Has anyone experienced this and/or know how to fix it?
Best Answer
Instead of putting it in
PROMPT_COMMAND
, put it inPS1
:When it's in
PS1
, bash counts the number of characters that get printed so that it can correctly redraw when you scroll through your history. That's why bash has the\[
and\]
special characters—they tell bash that the enclosed characters are not printable, which helps bash figure out how to redraw the prompt when necessary.Note that the command substitution is inside the single quotes. This prevents expansion at assignment time. If the command substitution was in double quotes or unquoted, the output of
myprompt
would be captured once at assignment time and remain static. In order to support variable values that change over time, the shell expands the value ofPS1
each time the prompt is displayed. This means that expansion should be prevented at assignment time by quoting. It also means that you need to be careful about speed: if the command substitution takes 1 second to complete, then your prompt will take 1 second to display.