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'm trying to set up a bash prompt for - hostname(screen#):directory$ which is coloured green if the last command completed successfully, red if not. This is what I have so far, which actually does the job but seems to cause display problems if the command wraps a line:

 PS1="\[\`if [[ \$? = "0" ]]; then echo '\e[32m'; else echo '\e[31m' ; fi\` - \h(${WINDOW}):\W$\e[00m "

Googling the issue I found this helpful SO post with a comment that mentions wrapping nonprinting characters in \\[ and \\] to avoid this issue. Therefore I tried the following, but it did not solve the issue, and furthermore breaks the colour change:

PS1="\[\`if [[ \$? = "0" ]]; then echo '\e[32m'; else echo '\e[31m' ; fi\`\] - \h(${WINDOW}):\W$\[\e[00m\] "

How can I keep the structure of this prompt, with colours, but fix it so that long commands are displayed properly?

share|improve this question

3 Answers 3

up vote 9 down vote accepted

I have a fancy prompt with colors, and now bash doesn't seem to know how wide my terminal is. Lines wrap around incorrectly.


I have another proper way to do this, put this code in your ~/.bashrc or create a new file and source file :

PROMPT_COMMAND=$(
    cat<<-'EOF'

    retval=$?

    RED=$(tput setaf 1)
    GREEN=$(tput setaf 2)
    STOP=$(tput sgr0)

    # arithmetic using bash parameter expansion on a array
    if (($retval + ${PIPESTATUS[@]/%/+} + 0)); then
        PS1="\[$RED\]\u@\h:\w$ \[$STOP\]"
    else
        PS1="\[$GREEN\]\u@\h:\w$ \[$STOP\]"
    fi
EOF
)

That will do the trick =)

Bash will run the code inside PROMPT_COMMAND for each commands.

If you have copy/paste problem, you can download the script

tput

EXPLANATIONS

  • (( )) is arithmetic in bash, see http://wiki.bash-hackers.org/syntax/arith_expr
  • PROMPT_COMMAND : if set, the value is executed as a command prior to issuing each primary prompt. See man bash | less +/PROMPT_COMMAND
  • tput is better than hard coding ANSI escape codes. See http://wiki.bash-hackers.org/scripting/terminalcodes
  • PIPESTATUS : An array variable containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command). See man bash | less +/PIPESTATUS
  • cat<<-'EOF' is a special here doc : the - character means I can indent code, and the single quotes on 'EOF' means to not interpolate variables
share|improve this answer
    
Added doc link about your problem –  sputnick Nov 20 '12 at 21:15
    
Thanks. I am getting an unexpected EOF while looking for matching `)' on the line that defines the function. Near as I can tell it seems that bash thinks that there is an unclosed ( in the do line, but I really don't see how that could be. –  dotancohen Nov 20 '12 at 22:07
    
This is a copy & paste problem, this will disappear if you reindent. –  sputnick Nov 20 '12 at 22:16
    
Actually, I did reindent, with tabs. Everything inside the function got one tab save for the lines that begin PS1, which got two tabs. –  dotancohen Nov 20 '12 at 22:26
    
Try copy & paste again, there was some mistakes. –  sputnick Nov 20 '12 at 22:31

Not \\[, just \[. You also have an extra \[ at the start.

share|improve this answer
    
Thanks, I updated the question. In fact, I had already taken care of the `\\` issue before I posted. –  dotancohen Nov 20 '12 at 19:12

I have a 2-line prompt, so the potentially long stuff won't affect the command line:

glennj@homebase ~/tmp
2219 $ set | grep PS1=
PS1='\n\u@\h \w\n\! \$ '
share|improve this answer

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.