BASH – customizing PS1 to run a command

I wanted to modify my PS1 to run some commands every time. Let’s say I want it so that if the last executed command was successful, it would add a green smile at the end of PS1, otherwise the smile should be red.
I extracted it to a function:

function exit_smile {

    EXITSTATUS="$?"
    RED="[e[1;31m]"
    GREEN="[e[32;1m]"

    if [ "${EXITSTATUS}" -eq 0 ]
    then
       SMILE="${GREEN}:)"
    else
       SMILE="${RED}:("
    fi

    echo -n "$SMILE"
}

and then tried both using `exit_smile` and $(exit_smile) when modifying the PS1 variable, but it executes it once when modifying PS1 or prints literal [e...] instead of a color.
For example

PROMPT="<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="750035">[email protected]</a>h W"
PS1="${PROMPT} $ $(exit_smile) ${OFF}n"

Gives [email protected] ~ $ [e[32;1m]:)
What am I missing?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I’m not sure if this has changed between versions(*), but my man page for Bash says that

Bash allows these prompt strings to be customized by inserting a number of backslash-escaped special characters that are decoded as follows:

(list contains e, [, ] etc.)

After the string is decoded, it is expanded via parameter expansion, command substitution, …

Which means that the [..] can’t come from the command substitution, but must be there before that.

(It also means you could use u or w as arguments to a command substitution, and they’d get replaced before the command runs. And I have no idea what putting [..] inside a command substitution would do… This would make more sense the other way around.)

So, we’ll have to put the color codes in separate expansions and protect them with [..] by hand. I’ll use variables instead of command substitution, and also the $'...' expansion to get the ESC character:

prompt_smile() {
        if [ "$?" = 0 ] ; then
                smile=' :) '
                smilecolor=$'e[1;32m'
        else
                smile=' :( '
                smilecolor=$'e[1;31m'
        fi
        normalcolor=$'e[0m'
}

PROMPT_COMMAND=prompt_smile
PS1='<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="354075">[email protected]</a>h W $ [$smilecolor]$smile[$normalcolor]n'

(* the reason I wonder about that, is that the answers to the older and similar but no so duplicate question seem to output the [..] from within an expansion)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x