Saturday, May 24, 2014

Раскрашиваем bash prompt

Существует множество вариантов кастомизации приглашения bash for fun and profit. Сегодня поговорим об использовании различных цветов в PS[1234].

Практически все терминалы нынче поддерживают 8 стандартных цветов + их "яркие" варианты. Итого - 16. Каждый цвет задается escape-последовательностью вида \e[0;3Nm либо \e[1;3Nm, где 0 ≤ N ≤ 7.

Для того, чтобы выделить какой-то фрагмент приглашения bash некоторым цветом, необходимо вставить перед ним соответствующую escape-последовательность. Например, для зеленого цвета - это \e[0;32m. Как учит man bash, все escape-последовательности нужно оборачивать в "\[" и "\]". Это необходимо для того, чтобы bash мог корректно посчитать длину prompt-a. Также не забываем вернуть цвет по умолчанию в конце.

Возьмем для примера дефолтный prompt ArchLinux-a PS1='[\u@\h \W]\$ ' и подсветим имя пользователя зеленым цветом, а хост - синим:
PS1='[\[\e[0;32m\]\u@\[\e[0;34m\]\h\[\e[0m\] \W]\$ '

Вместо того, чтобы вставлять escape-последовательности напрямую в prompt, я предпочитаю использовать коротенькую функцию, в которую можно передать значения 0..15:
function fgcolor {
echo "\[\e[$(($1/8));3$(($1%8))m\]"
}

function resetcolor {
echo "\[\e[0m\]"
}

Соответственно, наш prompt принимает гораздо более читабельный вид:
PS1="[$(fgcolor 2)\u@$(fgcolor 4)\h$(resetcolor) \W]\\$ "

В принципе, на этом можно было бы и остановиться. Но лично я нахожу палитру в 16 цветов довольно ограниченной. К счастью, большинство терминалов уже поддерживают 256 цветов (а некоторые и больше). Поэтому если вы используете xterm, eterm, konsole или gnome terminal - можете смело использовать вместо стандартной escape-последовательности \e[38;5;Nm, где 0 ≤ N ≤ 255. Коды первых 16 цветов совпадают с ANSI, что позволяет модифицировать функцию fgcolor для работы с любым терминалом:
function fgcolor {
if [ $1 -lt 16 ]; then
echo "\[\e[$(($1/8));3$(($1%8))m\]"
else
echo "\[\e[38;5;$1m\]"
fi
}

Чтобы вывести все 256 цветов с их кодами, можно воспользоваться следующим однострочником:


for c in {0..255}; do echo -en "\e[38;5;${c}m ${c}\t\e[0m"; [ $(((c+1) % 10)) -eq 0 ] && echo; done;

С 256 цветами пространство для творчества значительно расширяется. В качестве упражнения остается детектирование текущего терминала и использование той палитры цветов, которая поддерживается терминалом ;)

No comments:

Post a Comment