BASH: personalizar PS1 para ejecutar un command

Quería modificar mi PS1 para ejecutar algunos commands todo el time. Digamos que lo quiero para que si el último command ejecutado fue exitoso, agregue una sonrisa verde al final de PS1, de lo contrario, la sonrisa debería ser roja.
Lo extraje a una 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" } 

y luego intenté usar ` exit_smile (rodeado de exit_smile ) y \$(exit_smile) al modificar la variable PS1, pero se ejecuta una vez cuando se modifica PS1 o se imprime literalmente \[\e...\] lugar de un color.
Por ejemplo

 PROMPT="\u@\h \W" PS1="${PROMPT} \$ \$(exit_smile) ${OFF}\n" 

Da username@hostname ~ $ \[\e[32;1m\]:)
¿Qué me estoy perdiendo?

No estoy seguro de si esto ha cambiado entre versiones (*) , pero mi página de manual para Bash dice que

Bash permite que estas cadenas de aviso se personalicen insertando una serie de caracteres especiales con escape de barra invertida que se decodifican de la siguiente manera:

(la list contiene \e , \[ , \] etc.)

Después de decodificar la cadena, se expande mediante la expansión de parameters, la sustitución de commands, …

Lo que significa que el \[..\] no puede provenir de la sustitución del command, sino que debe estar allí antes de eso.

(También significa que podría usar \u o \w como arguments para una sustitución de command, y que serían reemplazados antes de que se ejecute el command. Y no tengo idea de qué sería lo que poner \[..\] dentro de una sustitución de command. .. Esto tendría más sentido al revés.)

Entonces, tendremos que poner los códigos de color en expansiones separadas y protegerlos con \[..\] a mano. Usaré variables en lugar de sustitución de commands, y también la expansión $'...' para get el carácter ESC:

 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='\u@\h \W \$ \[$smilecolor\]$smile\[$normalcolor\]\n' 

(* la razón por la que me pregunto sobre eso, es que las respuestas a la pregunta más antigua y similar pero no tan duplicada parecen dar como resultado el \[..\] desde dentro de una expansión)