Так Вам нравится цвет!!! (Таинственные символы ^[[)
Автор: © Pradeep Padala
| ||
Пробовали ли вы когда-нибудь перенаправлять вывод программы, использующей библиотеку curses? Удивляли ли вас таинственные символы ^[[ ? Пробовали ли вы получать цвета с помощью команды printf, без использования библиотек curses? Если хотя бы на один из этих вопросов ответ - "да", то эта статья для вас... Статья попытается объяснить загадочные символы, которые можно найти в выводе "curses-программы", работающей с цветами. Потом, мы расширим наши представления, дабы получать цвета с помощью обычной команды printf. Терминальные кодыВ старые времена телетайпных терминалов, последние находились далеко от компьютеров и были связаны с ними последовательными кабелями. Терминалы могли быть настроены с помощью посылки набора байтов к каждому из них. Всеми возможностями терминалов можно было управлять такими наборами байтов, которые обычно назывались эскейп-последовательностями (esc-последовательностями), потому как начинаются они с символа escape(0x1B). Даже в наши дни, работая с эмуляцией терминала vt100, мы можем послать esc-последовательность эмулятору, и это будет иметь тот же эффект, что и на терминале. Наберите на вашей консоли следующее: echo "^[[0;31;40mIn Color" Первый символ является символом escape, и выглядит как два символа ^ и [. Что бы ввести этот символ, вам необходимо нажать CTRL+V а потом клавишу ESC. Все остальные символы являются обычными печатными. Вы увидите строку "В цвете" красного цвета. Консоль так и останется в режиме красного цвета и что бы вернуть обычное состояние, надо ввести теперь: echo "^[[0;37;40m" Как вы можете видеть, достаточно просто устанавливать и сбрасывать цвет. Существует несметное число esc-последовательностей, с помощью которых вы можете выполнять множество вещей, как-то: перемещать курсор, сбрасывать терминал и т.п. Последовательность для установки цветов:
|
#include <stdio.h> #define RESET 0 #define BRIGHT 1 #define DIM 2 #define UNDERLINE 3 #define BLINK 4 #define REVERSE 7 #define HIDDEN 8 #define BLACK 0 #define RED 1 #define GREEN 2 #define YELLOW 3 #define BLUE 4 #define MAGENTA 5 #define CYAN 6 #define WHITE 7 void textcolor(int attr, int fg, int bg); int main() { textcolor(BRIGHT, RED, BLACK); printf("В цвете\n"); textcolor(RESET, WHITE, BLACK); return 0; } void textcolor(int attr, int fg, int bg) { char command[13]; /* Command - это управляющая команда терминалу */ sprintf(command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40); printf("%s", command); } |
Функция textcolor() - аналог функции API из Turbo C . Вы вызываете функцию для установки цвета, а после выводите информацию командой sprintf() (функция, которая используется в Turbo C для вывода в цвете).
#include <stdio.h> #define RESET 0 #define BRIGHT 1 #define DIM 2 #define UNDERLINE 3 #define BLINK 4 #define REVERSE 7 #define HIDDEN 8 #define BLACK 0 #define RED 1 #define GREEN 2 #define YELLOW 3 #define BLUE 4 #define MAGENTA 5 #define CYAN 6 #define WHITE 7 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) char *attrs[] = {"NORMAL", "BRIGHT", "DIM", "UNDERLINE", "BLINK", "REVERSE", "HIDDEN", "EXIT"}; char *colors[] = {"BLACK", "RED", "GREEN", "YELLOW", "BLUE", "MAGENTA", "CYAN", "WHITE", "EXIT"}; void textcolor(int attr, int fg, int bg); int print_menu(char *array[], int n_options, char *title); int main() { int attr, fg, bg; int attr_size, colors_size; attr_size = ARRAY_SIZE(attrs); colors_size = ARRAY_SIZE(colors); while(1) { printf("\n"); attr = print_menu(attrs, attr_size, "Выберите атрибут:"); if(attr == attr_size - 1) break; fg = print_menu(colors, colors_size, "Выберите цвет символов:"); if(attr == colors_size - 1) break; bg = print_menu(colors, colors_size, "Выберите цвет фона:"); if(attr == colors_size - 1) break; printf("\n"); textcolor(attr, fg, bg); printf("Это - пример того, что вы получите, используя комбинацию атрибута %s, цвета символов %s, и цвета фона - %s", attrs[attr], colors[fg], colors[bg]); textcolor(RESET, WHITE, BLACK); system("clear"); } return 0; } int print_menu(char *array[], int n_options, char *title) { int choice, i; for(i = 0;i < n_options; ++i) printf("%d.%s\n", i, array[i]); printf("%s", title); scanf("%d", &choice); return choice; } void textcolor(int attr, int fg, int bg) { char command[13]; /* Command - это управляющая команда терминалу */ sprintf(command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40); printf("%s", command); } |
Эта программа получает набор атрибутов от пользователя и выводит текстовую строку с указанными атрибутами и цветами. Обычно, я использую её для нахождения красивых комбинаций цветов для моих программ. Текстовая версия программы находится тут .
В чем же выгода? Если получение цветов так просто, почему люди гробят своё время на написание громоздких программ с помощью curses, которая направляет запрос в базу данных terminfo общим путём? Как мы знаем, существует много типов терминалов с малыми возможностями и терминалов, которые не распознают указанных esc-последовательностей, либо имеют другой набор кодов. Так что, если вы хотите написать портируемую программу, которая работала бы с любым терминалом с аналогичной (или уменьшенной) функциональностью, вы должны использовать библиотеку curses. Она использует базу terminfo для нахождения верных последовательностей, необходимых для корректного выполнения задачи. Terminfo - это большая база, которая содержит информацию о различных возможностях разных терминалов.
Если же вы желаете написать маленькую программу, которая работает с цветами на консоли Linux, либо в окне эмулятора xterm, вы можете преспокойно использовать esc-последовательности. Консоль Linux, в основном, эмулирует vt100, так что она понимает указанные выше последовательности.
Существует, однако, способ сделать запрос к базе данных terminfo и выполнить соответствующие указания. Команда tput посылает запрос и выполняет указанную вами функцию. Две опции setf и setb используются для установки цвета текста и фона. Что бы установить цвет текста в красный, а цвет фона в зелёный, необходимо выполнить следующие команды:
tput setf 4 # tput setf {номер цвета символов } tput setb 2 # tput setb {номер цвета фона}
Это можно использовать в сценариях shell где угодно. Другие возможности команды tput описаны в руководстве. Руководство по terminfo содержит много информации, касающейся возможностей терминалов - как получить и установить их значения и многое другое. Есть два руководства по terminfo. "man 5 terminfo" описывает базу данных terminfo. "man 3ncurses terminfo" описывает C-функции, которые используют эту базу.
Тут приведены номера цветов, которые нужно передавать в качестве аргументов командам "tput setf" и "tput setb".
0 чёрный 1 красный 2 зелёный 3 жёлтый 4 синий 5 фиолетовый 6 голубой 7 белый
Веселитесь!!!