A dumb devil



Responsive colors for the Bash shell prompt

Here's a Bash shell tip for changing the prompt's colors to indicate the success or failure of the last command. You can set the background or foreground colors based on an arithmetic expression.

Let's set the background to green for successful commands, and red for the commands that failed. We'll use the commands "true" and "false" as handy example commands.

The trick is that bash's (( )) construct lets you evaluate $?, the exit status of the last command, when it evaluates $PS1.

From Bash tips: Colors and formatting we can see that \e[41m is the control sequence for the red background color and \e[42m is the control sequence for the green background color. So what we need to do is create an expression that evaluates to 42 on success (exit status 0) and 41 for any other value of $?

simple_bash_background.png

So the expression we use is: ((!$?+41)).

If $? is 0, then !$? is 1, and ((1+41)) = 42. Otherwise, if $? is anything but 0, then the expression becomes ((0+41)) = 41.

For my PS1, I use the 256-color black background \e[48;5;16m for successful commands, and a deep red \e[48;5;52m for failed commands. So the math becomes a little more complicated:

my_bash_background.png

My expression is ((!!$?*36+16)). Successful commands (exit code 0) make !!$? evaluate to 0, so we get ((0*36+16)) = 16. Otherwise, it becomes ((1*36+16)) = 52.

Using a little math you can customize your bash prompt in various ways to indicate the success or failure of the last command!

Edit: The only constant is change

The truth is, I've since changed my prompt. Here's what it looks like nowadays:

ps1.png

I don't just use bash's arithmetic construct anymore, I use an "if" expression in the prompt to decide to print the checkmark or the cross-out character. I think this is more pleasing then the change in background color. It sort of corresponds to the following:

PS1='$(if [ $? -eq 0 ]; then \
   echo -e "\[\e[32m\]\xe2\x9c\x93"; \
else \
   echo -e "\[\e[31m\]\xe2\x9c\x97"; \
fi) \[\e[38;5;242m\]\w$\[\e[0m\] '

2 Comments on "Responsive colors for the Bash shell prompt "

  1. dblume on April 22nd, 2018

    After composing this post, I saw that Supriyo Biswas explains another way to make the prompt responsive by embedding $(if ... fi) logic in the prompt. That's really handy, too.

  2. James on April 23rd, 2018

    Good tip David. I use unicode checmark/and X coloured in green and red for a similar effect:

    I define:
    CHECKMARK=\342\234\223
    CROSSMARK=\342\234\227

    export SUCCESS_COLOR=${COLOR_GREEN}
    export SUCCESS_SYMBOL=${CHECKMARK}

    Then use: a function:
    # Start of prompt that indicates command success
    function check_last_command()
    {
    if [ $? == 0 ]; then
    export SUCCESS_COLOR=${COLOR_GREEN}
    export SUCCESS_SYMBOL=${CHECKMARK}
    else
    export SUCCESS_COLOR=${COLOR_RED}
    export SUCCESS_SYMBOL=${CROSSMARK}
    fi
    export PS1="${SUCCESS_COLOR}${MYPS1}"
    }

    Then i use the bash environment variable PROMPT_COMMAND to run the check_last_command function like so:

    export PROMPT_COMMAND=check_last_command

Comments are closed.