Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Clarification: I want __foo to be executed each time the PS1 string is presented in the terminal, not when the PS1 string is constructed (hence its being in quotes). __foo contains logic that examines the current directory, so its execution must be deferred.


I'm trying to use different colours in my Bash PS1 string from within a Bash function:

LIGHTRED="\033[1;31m"
LIGHTGREEN="\033[1;32m"
RESET="\033[m"

__foo () {
    # Do some stuff and genereate a string to echo in different colours:
    echo -n '\['$1'\]firstcolour \['$2'\]secondcolour'
}

PS1='$(__foo '$LIGHTRED' '$LIGHTGREEN')\['$RESET'\] \$'

Essentially I want __foo to generate part of the PS1 in a bunch of different colours. My attempt doesn't seem to work, though; it produces the following output:

-bash: 31m: command not found
-bash: 32m: command not found
\[]firstcolour \[\]secondcolour $

What gives, and how can I fix it?

share|improve this question
add comment

3 Answers

up vote 2 down vote accepted

Use the Bash environment variable $PROMPT_COMMAND to redefine the $PS1 variable just before the prompt is displayed.

LIGHTRED='\033[1;31m'
LIGHTGREEN='\033[1;32m'
RESET='\033[m'

__foo () {
  # Do some stuff and genereate a string to echo in different colours:
  echo -n "\[$1\]firstcolour \[$2\]secondcolour"
}

PROMPT_COMMAND=$PROMPT_COMMAND'; PS1="$(__foo $RED $GRN)\[$OFF\]\n\$ "'

Note two additional changes that I have made to your code are optional here. They were added because I think it clarifies where/where not the escape codes get expanded:

  • Hard quotes ' around the color definition variables.
  • Soft quotes " around the return string for __foo
share|improve this answer
    
What's the advantage of using $PROMPT_COMMAND to set $PS1 instead of just having a dynamic $PS1 string? –  Will Vousden Sep 18 '12 at 9:51
    
I think the quoting is easier using PROMPT_COMMAND; you don't need to create a string that runs a command every time it is evaluated; you just evaluate the dynamic parts and put the result in PS1. –  chepner Sep 19 '12 at 19:09
    
@WillVousden -- Zero advantage. It is just an answer that will work. I provided this one because I guessed no one else would suggest solving the question with this approach. –  zero2cx Sep 20 '12 at 5:00
    
Thanks; I wasn't aware of $PROMPT_COMMAND, so that's good to know! –  Will Vousden Sep 20 '12 at 9:54
add comment

Your function foo returns a string which is executed by bash as a command, since you surrounded it with $() (and escaped all variable substitution with single quote marks.

Changing your code to this make it work just fine:

LIGHTRED="\033[1;31m"
LIGHTGREEN="\033[1;32m"
RESET="\033[m"

__foo () {
  # Do some stuff and genereate a string to echo in different colours:
  echo -n '\['$1'\]firstcolour \['$2'\]secondcolour'
}

PS1=$(__foo $LIGHTRED $LIGHTGREEN)\[$RESET\]\$
share|improve this answer
    
I should've been clearer in my question: I want __foo to be executed each time the PS1 string is presented at the terminal, not when the script is executed. I've updated my question. How can I do this? –  Will Vousden Sep 17 '12 at 21:05
add comment

I've solved it:

LIGHTRED="\033[1;31m"
LIGHTGREEN="\033[1;32m"
RESET="\033[m"

__foo () {
    # Do some stuff and genereate a string to echo in different colours:
    echo -n '\['$1'\]firstcolour \['$2'\]secondcolour'
}

PS1='$(__foo "'$LIGHTRED'" "'$LIGHTGREEN'")\['$RESET'\] \$'

The arguments to __foo needed to be enclosed in quotes.

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.