2012-03-30 10 views
10

Devo essere in grado di essere in grado di rendere il testo sul terminale più evidente e ciò che ho pensato è stato quello di rendere il testo colorato. O il testo attuale, o lo spazio nel rettangolo-ogni cosa di ogni lettera (si pensi al cursore di vi). Le uniche due specifiche extra che penso siano importanti per la mia applicazione sono: il programma dovrebbe essere distro-indipendente (una certezza è che il codice verrà eseguito solo in BASH), e non dovrebbe produrre caratteri extra quando si scrive su un file (sia dal codice vero, sia per il piping dell'output)Uscita a colori del programma eseguito in BASH

Ho cercato nel web alcune informazioni, ma ho potuto trovare solo informazioni per il cstdlib deprecato (stdlib.h), e ho bisogno (in realtà, è più di un "voglio") per farlo usando la funzionalità di iostream.

risposta

12

La maggior parte dei terminali rispetta le sequenze di colori ASCII. Funzionano emettendo ESC, seguito da [, quindi un elenco separato da punto e virgola di valori di colore, quindi m. Questi sono valori comuni:

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 

Così l'output "\033[31;47m" dovrebbe rendere il (testo) di colore davanti terminale rosso e il colore di sfondo bianco.

Si può avvolgerlo bene in un C++ modulo:

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"; 
} 
+1

Non dimenticare la terminazione ' 'm'' della sequenza, come' "\ 033] 31; 47m" '. –

+0

@JoachimPileborg: corretto. – orlp

4

Ecco una versione del codice sopra da @nightcracker, utilizzando stringstream anziché itoa. (Questo viene eseguito utilizzando clang ++, C++ 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; 
} 
Problemi correlati