Цветной вывод программы под BASH

Мне нужно уметь сделать текст на терминале более заметным, и я подумал, что текст должен быть покрашен. Либо фактический текст, либо пробел в каждом прямоугольнике письма-thingy (думаю, курсор vi). Единственные две дополнительные спецификации, которые, как мне кажется, важны для моего приложения: программа должна быть независимой от дистрибутива (уверенность в том, что код будет работать только под BASH), и он не должен выводить лишние символы при записи в файл (либо из фактического кода, либо при конвейерном выходе)

Я искал в Интернете некоторую информацию, но я мог найти информацию только для устаревшего cstdlib (stdlib.h), и мне нужно (на самом деле, это больше "хочу" ) сделать это, используя функциональность iostream.

Ответ 1

Большинство терминалов относятся к цветовым последовательностям ASCII. Они работают, выводя ESC, а затем [, затем список цветов, разделенных точкой с запятой, затем m. Это общие значения:

Special
0  Reset all attributes
1  Bright
2  Dim
4  Underscore   
5  Blink
7  Reverse
8  Hidden

Foreground colors
30  Black
31  Red
32  Green
33  Yellow
34  Blue
35  Magenta
36  Cyan
37  White

Background colors
40  Black
41  Red
42  Green
43  Yellow
44  Blue
45  Magenta
46  Cyan
47  White

Таким образом, вывод "\033[31;47m" должен сделать красный цвет фона терминала (текста), а цвет фона белым.

Вы можете легко обернуть его в форме С++:

enum Color {
    NONE = 0,
    BLACK, RED, GREEN,
    YELLOW, BLUE, MAGENTA,
    CYAN, WHITE
}

std::string set_color(Color foreground = 0, Color background = 0) {
    char num_s[3];
    std::string s = "\033[";

    if (!foreground && ! background) s += "0"; // reset colors if no params

    if (foreground) {
        itoa(29 + foreground, num_s, 10);
        s += num_s;

        if (background) s += ";";
    }

    if (background) {
        itoa(39 + background, num_s, 10);
        s += num_s;
    }

    return s + "m";
}

Ответ 2

Здесь приведен код выше из @nightcracker, используя stringstream вместо itoa. (Это выполняется с использованием clang++, С++ 11, OS X 10.7, iTerm2, bash)

#include <iostream>
#include <string>
#include <sstream>

enum Color
{
    NONE = 0,
    BLACK, RED, GREEN,
    YELLOW, BLUE, MAGENTA,
    CYAN, WHITE
};

static std::string set_color(Color foreground = NONE, Color background = NONE)
{
    std::stringstream s;
    s << "\033[";
    if (!foreground && ! background){
        s << "0"; // reset colors if no params
    }
    if (foreground) {
        s << 29 + foreground;
        if (background) s << ";";
    }
    if (background) {
        s << 39 + background;
    }
    s << "m";
    return s.str();
}

int main(int agrc, char* argv[])
{
    std::cout << "These words should be colored [ " <<
        set_color(RED) << "red " <<
        set_color(GREEN) << "green " <<
        set_color(BLUE) << "blue" <<
        set_color() <<  " ]" << 
        std::endl;
    return EXIT_SUCCESS;
}

Ответ 4

Вы также можете создать пользовательскую функцию, например:

void textcolor(int color)
{
    std::cout<<"\033]"<<color;
}

Подробнее читайте http://en.wikipedia.org/wiki/ANSI_escape_code