Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question

migrated from stackoverflow.com Feb 14 '12 at 15:15

This question came from our site for professional and enthusiast programmers.

add comment

2 Answers 2

Instead of putting it in PROMPT_COMMAND, put it in PS1:

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

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 of PS1 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.

share|improve this answer
    
Thanks, but wouldn't that statically assign the output of myprompt to PS1? I remember trying to do something like that before. –  adrusi Feb 13 '12 at 3:22
1  
Oops, that's a bug. I fixed it. The command substitution should be inside the single quotes. I'm in the habit of expanding variables and command substitutions at assignment time because that's what I want 99% of the time. PS1 is one of the rare exceptions. –  Richard Hansen Feb 13 '12 at 14:57
    
Thanks for the detailed explanation; this has helped me fix my PS1. I had PS1='\033]0;\u@\h\007[\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]]\$ ' which sets the window title and shows 'user@host full-path $' but the cursor was wrapping unexpectedly. After adding \[ and \] to look like this: PS1='\[\033]0;\u@\h\007\][\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]]\$ ' it works fine! –  Benjamin Goodacre Jun 30 at 10:52
add comment

PROMPT_COMMAND can contain a command that is executed before the new prompt is printed by bash (so before PS1 is evaluated).

With git 1.8.1, code to do this effectively with PROMPT_COMMAND was released. See using git-prompt.sh with PROMPT_COMMAND. The code can work with earlier versions of git, just copy the file contrib/completion/git-prompt.sh to a place where you can source it from your .bashrc.

Cheers

Simon

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.