Bash Prompt #6: Return Value in the Prompt

Bash Prompt Index

Many, many years ago, I was surprised to find a coworker whose prompt was 0$ . That was it, not even the current working directory. He said "I can type pwd if I forget that." But his prompt had a feature I've come to value over the years: when the previous command failed and returned a non-zero return value, the prompt would change to show that: 1$. It doesn't seem like much, but it's a huge help to have a visual cue when a command has failed. Here's the original version:

PS="\$?\\\$ "

The return value is $? but it needs to be escaped or it's interpreted when the PS1 string is loaded and then never again: we want it to be dynamic. The escaped dollar sign is a dollar sign for a regular user, or a hash mark for the root user.

Here's the whole thing wrapped in a more complex but more useful structure:

ERRCOLOUR='\001\033[48;5;007m\002\001\033[38;5;009m\002'
NOCOLOUR='\001\033[0;0m\002'

prompt_command () {
    _p_retval=$?;
    if (( _p_retval == 0 )); then
        _p_retval="";
    fi;
}

PROMPT_COMMAND=prompt_command

PS1="${ERRCOLOUR}\${_p_retval}${NOCOLOUR}\\\$ "

This shows the error code (if it's non-zero) in red on a white background just before the $ in the prompt:

screenshot: p_retval is a file containing the above code

basic return value prompt, and prompt with colourized return value

The code requires a bit of explanation:

  • see the entry on colours if those escape sequences aren't familiar
  • I write complex prompts, so I use the preface "_p_" to namespace (not a verb, but you know what I mean ...) variables that are used solely by the prompt
  • why not just throw $? straight into the prompt? Two reasons: 1) I wanted a way to not show the return code if the value was zero, and in a more complicated prompt that runs other commands, it's necessary to capture the return value before it's overwritten by commands run as part of the construction of the prompt.
  • the function PROMPT_COMMAND is always run by Bash just before the prompt is displayed
  • what's with the redundant PROMPT_COMMAND=prompt_command line, why not just assign the code straight to PROMPT_COMMAND? It's turned out to be a lot easier to indirectly build a function (prompt_command()) and call that than build it directly, so I always do it this way.