Цветной текст в консоли Linux #3. Улучшаем совместимость скрипта.

Преамбула

Друзья [info]ketmar@ljr и [info]grusha@ljr отправили мне несколько ценных замечаний по поводу покраски консоли из скрипта (копия). Решил про них здесь отдельно написать, и модифицировать скрипт

Замечание #1, попадание ESC-последовательностей в поток, при вызове скрипта в потоке

Решил начать с него, оно более важное.
Впрочем, отдельно ему посвятил маленькую заметку (копия), где описал проблему и ее решение, так что осталось только применить, оборачиваю основной код функции echoc() в if, осушествляющий проверку, вызвали ли скрипт в терминале или в потоке:

if [ -t 1 ];then
	E__="\x1b[${FGROUND[$2]}m"
	if [ -n "$3" ];then
		E__="$E__\x1b[${BGROUND[$3]}m"
	fi

	if [ -n "$4" ];then
		E__="$E__\x1b[$4""m"
	fi

	echo -e "$E__$1\x1b[0m"

else
	echo "$1"
fi

Если не в терминале, просто выводим обычный текст без ESC-кодов:

В функции echocn() поступаем аналогично, просто к вызову echo не забываем добавить пареметр -n:

if [ -t 1 ];then	
	...
	echo -e -n "$E__$1\x1b[0m"

else
	echo -n "$1"
fi

Замечание #2. Совместимость цветов.

коды для яркости не входят в общепринятый стандарт VT-100, это расширение, и поддерживается далеко не всеми. один из стандартных способов увеличить яркость — включить полужирный режим: «\e[1;32m». да, это не работает для фона, стандартного метода для фона нет..

Т.е. максимально совместимыми цветами с терминалом являются только первые 7: коды 30..37 для текста, 40..47 для фона, дефолтные коды 39 и 49 для текста и фона соответственно (см. таблицу из предыдущей заметки (копия)).

Коды для яркости текста (90..97) и фона (100..107) расширение стандарта и поддерживаются не всеми терминалами. Для текста есть способ увеличить яркость — включить полужирный режим: семь цветов плюс полужирный с расчётом на то, что это давно уже яркость текста.

Совместимые цвета и стили

Итого, получаем вот такую таблицу совместимых цветов:

# Название цвета Код цвета текста Код цвета фона
0 Default (По умолчанию) 39 49
1 Black (Черный) 30 40
2 DarkRed (Темно-красный) 31 41
3 DarkGreen (Зеленый) 32 42
4 DarkYellow (Темно-желтый) 33 43
5 DarkBlue (Синий) 34 44
6 DarkMagenta (Темно-фиолетовый) 35 45
7 DarkCyan (Темный аквамарин) 36 46
8 Gray (Серый) 37 47
9 DarkGray (Темно-серый) 1;30
10 Red (Красный) 1;31
11 Green (Ярко-зеленый) 1;32
12 Yellow (Желтый) 1;33
13 Blue (Голубой) 1;34
14 Magenta (Фиолетовый) 1;35
15 Cyan (Аквамарин) 1;36
16 White (Белый) 1;37

Код сброса: \x1b[0m — сбрасывает настройки консоли (цвет текста, фона и стиль) к значению по умолчанию. Он работает нормально.

Заодно уж выбросил из таблицы стилей «мигающий» и «невидимый», которые объективно не работают:

Код стиля Стиль текста
0 Default (По умолчанию)
1 Bold (Жирный/яркость текста)
4 Understrike (Подчеркнутый)
7 Inversing (Инверсия), цвет фона и текста меняются местами

Модифицируем скрипт

Массивы с кодами цветов теперь выглядят так (массив с именами показан для лучшего понимания):

NAMES=(Default Black DarkRed DarkGreen DarkYellow DarkBlue DarkMagenta DarkCyan Gray DarkGray Red Green Yellow Blue Magenta Cyan White)
FGROUND=("39" "30" "31" "32" "33" "34" "35" "36" "37" "1;30" "1;31" "1;32" "1;33" "1;34" "1;35" "1;36" "1;37")
BGROUND=(49 40 41 42 43 44 45 46 47)

И подправляем вывод:

echo -e "Foreground color:\tBackground color:"

for N in {0..16}; do
    if [ $N -eq 1 ];then #foreground
	echocn "$N - ${NAMES[$N]}" $N 4
    else
	echocn "$N - ${NAMES[$N]}" $N
    fi
    echo -e -n "\t\t"
    
    if [ $N -le 8 ];then
	if [ $N -gt 1 ];then
	    echoc " ${NAMES[$N]} " 1 $N #background
	else
	    echoc " ${NAMES[$N]} " 0 $N
	fi
    else
	echo
    fi
done
echo
echocn "Default" 0 0 0; echo -n " "
echocn "Bold" 0 0 1; echo -n " "
echocn "Understrike" 0 0 4; echo -n " "
echocn "Inversing" 0 0 7; echo -n " "
echo
echo

Что получилось

Вывод в терминал:

Вывод в файл:

./esccolorscomp >test.txt

Замечание #3. Об использовании tput

Я задал вопрос, а не проще ли вместо ESC-кодов использовать tput, о чем я уже писал (копия). Ответ был таким: Он требует установленого ncurses, в общем и целом — никто не гарантирует его наличия.

Готовый скрипт

На GitHub

Электронная книга Dexp M8 Prudentia, драйвера для Windows 7.

Немала баба клопоту, купила порося, в смысле немал клопоту я, но повелся на скидку и связался с дерьмоконторой DNS и ее клоном DEXP. Прошлая книжка у меня была Амазон Киндл, и я ее еще в Киеве купил, впрочем, так бы ей и пользовался, если бы на нее жопой не села бухгалтерша. Напрягать тетку не стал, выбрал чего подешевле. Естественно, задача была перекинуть книжки с той на эту, и если эту у меня винда прекрасно видела, то видеть эту наотрез отказалась.

На сайте говно-DNS, дерьмо-DEXP и в сраной инструкции естественно, «это ж хуй, я вопрос отгадала», т.е. не драйверов, ни того, где их искать. Т.е контора просто пиздец клиентоориентированная. Кроме флешек вообще лучше ничего у них не покупать. Правда, кнопочные телефоны DEXP еще хорошие, у правильного дядюшки Ляо заказывают, кирпич неубиваемый от слова «даже об голову Кивы».

Пришлось для простейшего подключения андроидной железяки включать мозг и заниматься детективным расследованием, правда, довольно простым.

Железка под Андроидом 8.1 и на чипе Rockchip PX30, так что подошли драйвера Rockchip 4.4

На всякий случай забэкапил

Rockchip Driver Assitant v4.4 на Mega.NZ (10 Mb, RAR)

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

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

Преамбула

А зачем? Это логическое продолжение темы (копия) про покраску текста в терминале. Если использовать ESC-последовательности, то они, что логично, попадут в файл, если пользователь перенаправит туда вывод скрипта, и получится бяка:

Потому, надо проверить, вызвали ли скрипт из терминала, или вывод скрипта перенаправлен в поток.

Решение

По итогам обсуждения с [info]ketmar@ljr и [info]grusha@ljr решение нашлось:

if [ -t 1 ];then
    echo -e "\x1b[32;1mRun in terminal\x1b[0m"
else
    echo "Run in pipe"
fi

Проверка

Вызов из терминала:
./testpipe
Run in terminal

Вызов в потоке:
./testpipe >test.txt

Содержимое файла test.txt:
Run in pipe

Тестовый скрипт

на GitHub