Search code examples
linuxbashshellcommand-promptprompt

coloured bash prompt which uses a function


I need to make a bash prompt that uses the data returned by another function. I need the prompt to support colour.

Toy case:

fx() {
...some processing...
# x is the result of some processing
color=x
echo "\[$(tput setaf ${color})\]${data_from_processing}\[${tput sgr0}\]"
}
PS1='fx'

But the above solution doesn't seem to work. What I expected is 'data' in the specified color. But what I get is \[\]<the correct data>\[\]. It should be noted that \]<the correct data\[ is in color.

enter image description here


Solution

  • The shell parses the value of PS1 (which includes recognizing the special escape sequences \[ and \]) before the command substitution is evaluated.

    The simplest fix is to replace \[ and \] with the actual bytes that the shell would:

    q() { printf '\001%s\002123\001%s\002' "$(tput setaf 1)" "$(tput sgr0)"; }
    

    However, I would recommend using PROMPT_COMMAND to assemble the value of PS1 rather than embedding a command substitution:

    q () { echo "\[$(tput setaf 1)\]123\[$(tput sgr0)\]"; }
    
    make_prompt () {
      PS1="$(q):"
    }
    PROMPT_COMMAND=make_prompt
    

    Of course, you can fold the definition of q directly into the definition of make_prompt if like. Note that we aren't delaying the call to q; it is called immediately to create the value of PS1 to use for each prompt.