This is what I use in my .bashrc
:
PS1_PROMPT() {
local e=$?
(( e )) && printf "$e|"
return $e
}
PS1='$(PS1_PROMPT)'"$PS1"
ibug@example:~ $ false
1|ibug@example:~ $ ^C
130|ibug@exame:~ $ true
ibug@example:~ $
This has the advantage over JoL's answer that the value of $?
is preserved after displaying (via return $e
). It's also basically a rework of Android's default /system/etc/mkshrc
that does the same job.
Note that $(PS1_PROMPT)
is enclosed in single quotes because $PS1
is evaluated every time it's printed, in addition to when set in a variable assignment expression, so single quotes prevents it from being evaluted right now and instead defers that to when printing.
Alternatively, as suggested by ilkkachu, you can make use of Bash PROMPT_COMMAND
special variable:
PS1_PROMPT() {
local e=$?
PROMPT_ECODE=
(( e )) && PROMPT_ECODE="$e|"
return $e
}
PROMPT_COMMAND=PS1_PROMPT
PS1='$PROMPT_ECODE'"$PS1"
This has one advantage that no subshell is spawned every time PS1 is printed.
PS1='$(echo -n)\[\e[0;$(($??0:91))m\]\$ \[\e[0m\]'
) — in this case, the return code is always 0 inside the PS1, even though I can query$?
on the command line and it has the correct value. – Konrad Rudolph Jun 09 '21 at 11:12$?
in a variable:PS1='_ps1err=$?;...;$((_ps1err?0:91))...
. – Kusalananda Jun 09 '21 at 11:45$((…))
, what you’ve posted won’t work directly). But then I’m getting the status echoed in my shell prompt. – Konrad Rudolph Jun 09 '21 at 12:07${_ps_err##[$((_ps_err=$?))0-9]*}
. This exploits the fact that[…]
is a valid pattern in the##
parameter expansion. The expansion will be the value of$?
followed by0-9
— in other words: an arbitrary digit. This is followed by a*
pattern that matches all the rest, to ensure that the entire previous value of_ps_err
is removed. – Konrad Rudolph Jun 10 '21 at 17:04