Жиль определил вашу главную проблему, но я хотел попытаться объяснить это по-другому.
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 .