Использование переменных для хранения цветовых кодов терминала для PS1?


33

В моем .bashrc, я использую цветовые коды терминала ANSI, чтобы раскрасить различные биты. Это выглядит так:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

где virtual_envи git_branchbash-функции, которые выводят материал на стандартный вывод.

Теперь, чтобы было легче читать и изменять, я хотел бы хранить цветовые коды в переменных и ссылаться на них, а не встраивать их непосредственно в PS1. Итак, у меня есть несколько переменных, как это:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

Я хотел бы иметь возможность написать что-то вроде:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

Но это не работает - цветовые коды отображаются в подсказке, как будто они сбежали. Цвета работают правильно, если я использую двойные кавычки вместо PS1, но тогда подсказка меняется только тогда, когда я это делаю source ~/.bashrc.

Я попробовал другие вещи , которые я видел , что люди делают - используя printf, используя одиночные кавычки для цветов, помещая \[и \]в PS1вместо переменного цвета, но ничего не похоже на работу.

Как я могу использовать переменные для цветовых кодов?


Можете ли вы дать нам свой .bashrc?
cuonglm

@cuonglm Все ваши .bashrc принадлежат нам? Я покажу себя.
CivFan

Ответы:


20

Решение состоит в том, чтобы заставить оболочку подставлять переменные цвета при определении приглашения, но не функции. Для этого используйте двойные кавычки, как вы изначально пробовали, но избегайте команд, чтобы они не оценивались до тех пор, пока не будет выведено приглашение.

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

Обратите внимание на \перед $()каждой команды.

Если мы повторим это, мы увидим:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

Как видите, переменные цвета были заменены, но не команды.


1
Это, похоже, не работает, если $ (git_branch) также пытается печатать, используя $ {YELLOW} и т. Д. Только в этом разделе вы все равно получите все символы [].
ВБ Рид

7

Проблема в том, что ваша переменная GREENсодержит литеральную строку, состоящую из «обратной косой черты, обратной косой черты, нуля, три, три» и так далее. Например, он не содержит управляющий символ ASCII, необходимый для изменения цвета вашего терминала.

Вы можете поместить управляющие символы в GREENYELLOWи RESET) вручную, но гораздо лучше использовать tputво-первых, чтобы вам не нужно было ничего кодировать жестко, и вы будете поддерживать любой тип терминала.

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

Причина, по которой мир ставит «обратный слеш ноль три три» и т. Д. Непосредственно в PS1том, что интерпретация определенных последовательностей с обратным слешем - это особенность подсказок bash (см. Раздел ПРЕДУПРЕЖДЕНИЕ в руководстве. Эта замена происходит перед расширением параметра, команда тем не менее, подстановка, арифметическое расширение и удаление кавычек не применяются к результатам всех этих других операций.


5
Делая это таким образом, вы должны обернуть переменные цвета \[\]внутри $PS1. Например: PS1='\u@\h:\w\[${YELLOW}\]'. Если вы этого не сделаете, и в итоге получите длинную команду, которая переносится на следующую строку, вы столкнетесь со всевозможными проблемами. Оболочка использует, \[\]чтобы определить, какие символы нельзя распечатать, поэтому она не учитывает их при расчете длины подсказки. Это необходимо, чтобы он мог правильно нарисовать линию, когда она превышает ширину терминала.
Патрик

Я не знал о tput, спасибо. Я пока воспользуюсь ответом Патрика, но я вернусь к этому, когда у меня будет шанс.
Исмаил Бадави

2

Измените способ заполнения $ GREEN, $ YELLOW и $ RESET:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

1
Это фактически делает то же самое, что и ответ Селады. Но Celada более портативен в случае, если терминал использует различные коды выхода для настройки цвета. У этого также будет та же проблема с многострочным приглашением.
Патрик

2
В \[…\]бит должен оставаться в приглашении, вы не можете запихнуть его в переменной. Вы полностью удалили его, что приведет к проблемам с отображением (курсор не находится в положении, в котором его ожидает bash).
Жиль "ТАК - перестань быть злым"

Помимо проблем @Patrick, echo -e не является переносимым.
Помощник

1
Непереносимость tput setafдает больше возможностей - не позволяет выбирать из «светлого» набора цветов, например, светло-голубого. Ответ @ Кира, однако, делает.
CivFan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.