Жиль определил вашу главную проблему, но я хотел попытаться объяснить это по-другому.
Bash интерпретирует экранирование специальных приглашений только перед раскрытием любых переменных в приглашении. Это означает, что использование \eпеременной, развернутой из приглашения, не работает, даже если она работает непосредственно в PS1.
Например, это работает как ожидалось и дает красный текст:
PS1='\e[1;31m this is in red '
Но это не так, он просто помещает литерал \eв приглашение:
RED='\e[1;31m'
PS1="$RED not in red "
Если вы хотите сохранить экранирование цвета в переменных, вы можете использовать ANSI-C quoting ( $'...'), чтобы поместить буквенный escape-символ в переменную.
Чтобы сделать это, вы можете изменить свое определение GREEN, REDи NONE, таким образом , их значение является фактической последовательностью выхода.
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
Если вы сделаете это, ваш первый PS1с одинарными кавычками должен работать:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
Однако тогда у вас возникнет вторая проблема.
Попробуйте запустить это, затем нажмите Up Arrow, затем Home, и ваш курсор не вернется к началу строки.
Чтобы исправить это, измените PS1на включение \[и \]вокруг цветовых escape-последовательностей, например
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
Вы не можете использовать get_exit_statusздесь должным образом, так как его вывод содержит как печатные (код выхода), так и непечатаемые символы (цветовые коды), и нет возможности правильно пометить его в приглашении. Помещение \[...\]будет помечено как непечатное полностью, что не правильно. Вам нужно изменить функцию, чтобы она печатала только правильный цветовой код, а затем заключить его \[...\]в подсказку.
\[есть\1и\[есть\2. Это соответствует некоторойRL_PROMPT_{START,END}_IGNOREвещи readline , которая просит ее игнорировать байты при подсчете длины подсказки на экране. См. Lists.gnu.org/archive/html/bug-bash/2015-08/msg00027.html .