отображение цветом в терминале
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
отображение цветом в терминале
Иногда возникает потребность выделять какие-то выводы в терминал цветом.
На то есть (описаны, используются) разные способы: ESC управляющие последовательности (использующиеся ещё со времён MS-DOS), возможности пакета ncurses и др.
Но проблема (неприятность) в том, что:
- при работе в Linux практически повсеместно используется эмулятор терминала в графическом окружении рабочего стола (DE)...
- в зависимости от вида DE (которых десяток или более: KDE, GNOME, Mate, Cinnamon, ...) + используемой программы эмулятора терминала (которых в каждом DE тоже может быть несколько штук) - отдельные ESC последовательности могут отрабатываться, а могут и нет... (у меня, пока , не отрабатываются ... или я ещё не разобрался почему)
- но ещё хуже, когда предстоит перенос кода программы в другую операционную систему, главным образом в Windows, с тем, чтобы и там в их текстовой консоли отображение делалось так же.
И вот есть тут такой проект C++ (подсказали), который позволяет управлять характеристиками вывода в терминал (не только цвет) независимо от платформы: rang.
Оно, обещано , работает равнозначно в коде Linux, Windows, MacOS и т.д.
Испытаем!
На то есть (описаны, используются) разные способы: ESC управляющие последовательности (использующиеся ещё со времён MS-DOS), возможности пакета ncurses и др.
Но проблема (неприятность) в том, что:
- при работе в Linux практически повсеместно используется эмулятор терминала в графическом окружении рабочего стола (DE)...
- в зависимости от вида DE (которых десяток или более: KDE, GNOME, Mate, Cinnamon, ...) + используемой программы эмулятора терминала (которых в каждом DE тоже может быть несколько штук) - отдельные ESC последовательности могут отрабатываться, а могут и нет... (у меня, пока , не отрабатываются ... или я ещё не разобрался почему)
- но ещё хуже, когда предстоит перенос кода программы в другую операционную систему, главным образом в Windows, с тем, чтобы и там в их текстовой консоли отображение делалось так же.
И вот есть тут такой проект C++ (подсказали), который позволяет управлять характеристиками вывода в терминал (не только цвет) независимо от платформы: rang.
Оно, обещано , работает равнозначно в коде Linux, Windows, MacOS и т.д.
Испытаем!
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
Т.е., как оказывается, у них там есть, и единственно нужен, заголовочный файл:Olej писал(а):Испытаем!
Код: Выделить всё
[olej@dell rang]$ ls -l rang.hpp
-rw-rw-r-- 1 olej olej 6540 июн 12 02:15 rang.hpp
Вот их же пример кода:
Код: Выделить всё
#include <iostream>
#include "rang.hpp"
using namespace std;
int main( int argc, char** argv ) {
cout << "No rang?"
<< rang::bg::red
<< rang::fg::gray
<< "RANG!!!"
<< rang::style::reset
<< endl;
}
P.S. Единственно, обращаю внимание, что компиляция требуется с указанием опциями совместимости со стандартом C++11 (2011 года):
Код: Выделить всё
[olej@dell rang]$ make rang-test
g++ -Wall -std=c++11 -O3 rang-test.cc -o rang-test
- Вложения
-
- rang.hpp
- (6.39 КБ) 100 скачиваний
-
- rang-test.cc
- (262 байт) 106 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
Этот вот новый интерес к такой теме возник из задачи (учебной, студенческой) ... вот как я её переформулирую, выбросив всё лишнее:Olej писал(а):Испытаем!
Вообще то говоря, никаких оговорок относительно языка текста (локализации) явно не оговаривается, но по контексту понятно, что текст там может быть, в том числе, русскоязычным. И, по хорошему, всё это должно реализовываться в типах wchar_t и wstring ... но именно разбиение на слова может нормально работать и на широких 4-байтных UTF-8 символах (это один из немногих редких случаях), и поэтому всё я сделаю в терминологии string:Программа читает текстовый файл (имя с расширением .dat, заданное в командной строке запуска).
После этого программа:
- выводит текст на экран дисплея;
- определяет количество символов в каждом слове;
- выбирает для показа самое короткое слово;
- выбранное слово выделяется цветом в выводимом тексте;
- при очередном нажатии клавиши Enter выделение перемещается на следующее по длине слово.
Код: Выделить всё
#include <locale>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
#include "rang.hpp"
vector<string>::iterator current;
ostream& operator <<( ostream& out, const vector<string>& v ) {
for( vector<string>::const_iterator i = v.begin(); i != v.end(); i++ )
if( i != current )
out << *i << " ";
else
out << rang::fg::red << *i << rang::style::reset
<< "[" << i->length() << "] ";
return out;
}
bool sort_function( vector<string>::iterator f, vector<string>::iterator s ) {
return f->length() < s->length();
}
int main( int argc, char** argv ) {
setlocale( LC_ALL, "rus" );
if( argc != 2 ) {
cerr << "не указан файл данных" << endl;
return 1;
}
ifstream fin;
fin.open( argv[ 1 ] );
if( !fin ) {
cerr << "файл данных не найден: " << argv[ 1 ] << endl;
return 1;
}
string line;
do {
getline( fin, line );
cout << line << endl;
} while( fin );
fin.close();
fin.open( argv[ 1 ] );
vector<string> vw{ istream_iterator<string>( fin ), istream_iterator<string>() };
cout << "- в вашем тексте слов: " << vw.size() << endl;
vector<vector<string>::iterator> vp( vw.size() );
unsigned np = 0;
for( vector<string>::iterator w = vw.begin(); w != vw.end(); w++ )
vp[ np++ ] = w;
sort( vp.begin(), vp.end(), sort_function );
cout << "дальше жмите Enter ..." << endl;
np = 0;
while( true ) {
current = vp[ np ];
getline( cin, line );
if( ++np >= vp.size() ) np = 0;
cout << vw << endl;
}
}
И то, как это выполняется, показано на картинке.
- Вложения
-
- task213s.cc
- (2.33 КБ) 106 скачиваний
-
- 213_2.dat
- (63 байт) 98 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
Там есть ещё ряд интересных деталей:Olej писал(а):И то, как это выполняется, показано на картинке.
- для того, чтобы не портить входной текст (не переставлять в бессмыслице слова в векторе vw), я сортирую не сами слова в тексте (по числу байт в слове), а через указатели (итераторы) на них в другом, смежном векторе vp;
- сортировка делается вызовом стандартного алгоритма быстрой сортировки из STL библиотеки C++ (стандартная библиотека):
Код: Выделить всё
sort( vp.begin(), vp.end(), sort_function );
- я не стал специально в этом месте записывать анонимною лямбда-функцию (как делаю это часто, и что здесь наиболее уместно), а специально выписал эту функцию отдельно для понятности (... ну и для облегчения себе отладки, сознаюсь );
- сортировка сортирует указатели строк (итераторы) в vp по длине (числу байт) в строках, на которые они (итераторы) указывают.
P.S. И я предполагаю обязательно показать это, выписанное через лямбда-функцию, как наиболее уместное решение ... но позже, когда отлажу и проверю этот вариант.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
И выглядит это (показываю только отличающийся оператор сортировки) как-то так:Olej писал(а):P.S. И я предполагаю обязательно показать это, выписанное через лямбда-функцию, как наиболее уместное решение ... но позже, когда отлажу и проверю этот вариант.
Код: Выделить всё
sort( vp.begin(), vp.end(),
[]( vector<string>::iterator f, vector<string>::iterator s )-> bool {
return f->length() < s->length();
} );
- Вложения
-
- task213sa.cc
- (1.61 КБ) 94 скачивания
-
- 213_1.dat
- (611 байт) 103 скачивания
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
Возвращаясь ещё раз к цветовой разметке вывода в терминал - на этот раз более простая и наглядная программа: разметить слова из текста, читаемого из файла, в различные цвета.
Выглядит это так:
А далее - так как это на картинке.
Код: Выделить всё
#include <fstream>
#include <sstream>
using namespace std;
#include "rang.hpp"
using namespace rang;
int main( int argc, char** argv ) {
const rang::fg clrs[] = { fg::red, fg::green, fg::yellow, fg::blue, fg::magenta, fg::cyan };
const int clsrn = sizeof( clrs ) / sizeof( clrs[ 0 ] );
if( argc != 2 ) {
cerr << "не указан файл данных" << endl;
return 1;
}
ifstream fin;
fin.open( argv[ 1 ] );
if( !fin ) {
cerr << "файл данных не найден: " << argv[ 1 ] << endl;
return 2;
}
int c = 0;
while( true ) {
string s;
getline( fin, s );
if( !fin ) return 0;
istringstream ss( s );
string w;
while( ss >> w )
cout << clrs[ c++ % clsrn ] << w << rang::style::reset << " ";
cout << endl;
}
}
Код: Выделить всё
[olej@dell color]$ ./color 1.txt
...
- Вложения
-
- color.tgz
- (152.53 КБ) 88 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
И совсем для простоты (объяснений): выделить минимальное и максимальное значение в массиве каким-нибудь цветом отличающимся от остальных элементов массива.
1. Это будет работать почти в любой операционной системе: Windows, Linux, MacOS.
2. Это нужно компилировать с опцией совместимости со стандартом C++11, так для упрощения записан код. Но это легко переписать (вместо auto записать реальный тип итераторов) так, чтобы всё было корректно и в более ранних стандартах C++.
Код: Выделить всё
#include <iostream>
#include <algorithm>
using namespace std;
#include "rang.hpp"
int main( int argc, char** argv ) {
int array[] = { 10, 9, 11, 8, 13, 6, 14, 4, 12, 2, 8 },
size = sizeof( array ) / sizeof( array[ 0 ] );
auto mm = minmax_element( array, array + size );
cout << "диапазон: '" << *mm.first << "' ... '" << *mm.second << "'" << endl;
for( auto ia = array; ia < array + size; ia++ )
if( ia == mm.first )
cout << rang::fg::red << *ia << rang::style::reset << ' ';
else if ( ia == mm.second )
cout << rang::fg::green << *ia << rang::style::reset << ' ';
else
cout << *ia << ' ';
cout << endl;
}
2. Это нужно компилировать с опцией совместимости со стандартом C++11, так для упрощения записан код. Но это легко переписать (вместо auto записать реальный тип итераторов) так, чтобы всё было корректно и в более ранних стандартах C++.
Код: Выделить всё
[olej@dell color]$ g++ -Wall -std=c++11 -O3 minmax.cc -o minmax
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: отображение цветом в терминале
Новая статья по цветовой разметке терминала:
ЦВЕТА ТЕРМИНАЛА LINUX
Подробнее Esc-последовательности - здесь: ANSI escape code.
ЦВЕТА ТЕРМИНАЛА LINUX
Пока это только ... познавательная информация, практическая ценность которой - херня. Но там можно извлечь информацию про Esc-последовательности, в том числе, и по управлению цветом.Январь 1, 2018
Подробнее Esc-последовательности - здесь: ANSI escape code.
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя