Cores terminal Linux [RESOLVIDO]

1. Cores terminal Linux [RESOLVIDO]

Leandro Cunha
Leandro_Cunha

(usa Debian)

Enviado em 05/05/2016 - 01:58h

Como faz cores no terminal Linux? Testei de tudo no Ubuntu e não deu certo.
OBS: Eu estou estudando programação em C e sou estudante de Sistemas de Informação.
Eu desde de já agradeço a ajuda.


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 05/05/2016 - 10:19h

Como você perguntou num fórum de programação em C voltada primeiramente para Linux, deixe eu responder como um programador em C no mundo UNIX.

Para manipular qualquer atributo do terminal, você deve usar os recursos da biblioteca de terminal (chamada “terminfo”, abreviação de “terminal information”, em alguns sistemas, e “termcap”, abreviação de “terminal capabilities”, em outros). Para tanto, seu programa em C deve incluir o cabeçalho <term.h> e, na hora de linkar o programa, você deve adicionar a biblioteca correspondente (flags “-ltinfo” ou “-ltermcap”, dependendo do sistema; o Linux usa a primeira).

A biblioteca de terminal usa uma interface única para diversos tipos de terminal, independentemente dos recursos que ele oferece. Se você faz o seu programa com essas interfaces, e calha de ter o seu programa executando num terminal que não suporta determinado recurso, ele simplesmente não vai ativar tal recurso, mas vai seguir executando.

Em muitos lugares, inclusive em várias postagens deste fórum, você vai encontrar gente indicando sequências de escape do padrão ANSI X3.64, que deveriam ser diretamente embutidas dentro do seu programa. Eu sou radicalmente contrário a esse uso porque, embora a grande maioria dos terminais do mundo UNIX (incluindo os emuladores de terminal, como xterm, gnome-terminal ou konsole, os consoles de texto do Linux e outros UNIXes que rodam em PCs, os gestores de janelas de texto, como screen e byobu etc.) sejam compatíveis com X3.64, não dá para assumir que essa compatibilidade será SEMPRE verdadeira. Aliás, é até muito comum encontrar terminais não compatíveis com ANSI nem qualquer outra coisa: basta pensar no Windows, cujo console de texto e emuladores de terminal não usam sequências de caracteres de controle, mas chamadas ao sistema operacional.

Quando eu comecei a mexer com UNIX, os terminais de texto da minha faculdade tinham emulação de dezenas de tipos de terminal diferentes, EXCETO ANSI X3.64 ou qualquer coisa dela derivada (como VT-100). Em terminais assim, aquelas sequências fixas embutidas no programa, além de não produzirem os efeitos desejados, tendem a produzir efeitos desagradáveis ou até mesmo nocivos. Se você usar terminfo ou termcap (inclusive para Windows), você pode ter a segurança de que se você solicitar um recurso que o terminal não suporte, não será gerado conteúdo destrutivo, e o pior que pode acontecer é algo não ficar na forma como você gostaria que ficasse.

No caso específico de cores, você deve chamar tparm(set_a_foreground, numero_da_cor) para obter a sequência correta que ajuste a cor de primeiro plano, e tparm(set_a_background, numero_da_cor) para a sequência que troca a cor de fundo. Se você passar um número de cor não suportado pelo terminal, a cor simplesmente não será trocada, e nada será enviado ou feito com o terminal em decorrência da tentativa de trocar a cor.

Eis um exemplo de programa que mexe com cores, que eu fiz há alguns anos, justamente para aprender a brincar com isso. Compile-o com o comando “gcc colormatrix.c -o colormatrix -ltinfo”. Na hora de rodar, experimente primeiro rodá-lo normalmente (e.g. “./colormatrix”, e depois veja quais as diferenças quando você altera o tipo do terminal (por exemplo: “env TERM=xterm-256color ./colormatrix”, “env TERM=xterm-16color ./colormatrix”, “env TERM=ansi ./colormatrix”, “env TERM=vt100 ./colormatrix”, “env TERM=vt100 ./colormatrix”, “env TERM=dumb ./colormatrix”).

// colomatrix.c
#include <term.h>
#include <stdio.h>
#include <unistd.h>


const char msg_8_colors[]="Tabela com 8 cores dos terminais compativeis com ANSI X3.64";
const char msg_8b_colors[]="Tabela com 8 cores dos terminais compativeis com ANSI X3.64 + opcao de bold";
const char msg_16_colors[]="Tabela com 16 cores do PC e/ou Xterm";
const char msg_256_colors[]="Tabela com 256 cores do Xterm (16 basicas acima, 216 RGB, 24 tons de cinza)";


int main(void){
int r, g, b, h;
int fg_color, bg_color;

setupterm(NULL, STDOUT_FILENO, NULL);

putp(exit_attribute_mode); /* limpa atributos de texto */
putp(clear_screen); /* limpa tela */
putp(tparm(cursor_address, 0, 0)); /* vai para 1ª linha, 1ª coluna */

printf("Número máximo de cores: %d\n\n", max_colors);

/* ‘columns’ e ‘lines’ são variáveis globais definidas pela biblioteca */
printf("%*s%s\n\n", (int)(columns+1-sizeof msg_8_colors)/2, "", msg_8_colors);
printf("%*s", (int)(columns-24)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r;
fg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %1d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');

printf("\n\n%*s%s\n\n", (int)(columns+1-sizeof msg_8b_colors)/2, "", msg_8b_colors);
printf("%*s", (int)(columns-24)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r;
fg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %1d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
printf("\n%*s", (int)(columns-32)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
fg_color=b+2*g+4*r;
bg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" N%1d ", fg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
printf("\n%*s", (int)(columns-32)/2, "");
putp(enter_bold_mode);
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
fg_color=b+2*g+4*r;
bg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" B%1d ", fg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');

printf("\n\n%*s%s\n\n", (int)(columns+1-sizeof msg_16_colors)/2, "", msg_16_colors);
for(h=0; h<=1; h++){
printf("%*s", (int)(columns-32)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r+8*h;
fg_color=(h+r+b+g>=2? 0: 15);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %2d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');
}

printf("\n\n%*s%s\n\n", (int)(columns+1-sizeof msg_256_colors)/2, "", msg_256_colors);
for(h=0; h<=1; h++){
printf("%*s", (int)(columns-40)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r+8*h;
fg_color=(h+r+b+g>2? 0: 15);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');
}
for(r=0; r<6; r++){
for(g=0; g<6; g++){
if(!(g&1))
printf("%*s", (int)(columns-60)/2, "");
for(b=0; b<6; b++){
bg_color=16+36*r+6*g+b;
fg_color=(r+g+b>=6? 16: 231);
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
putp(exit_attribute_mode);
if(g&1)
putchar('\n');
}
}
printf("%*s", (int)(columns-60)/2-8, "");
bg_color=16;
fg_color=231;
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" (0/16) ");
fflush(stdout);
for(h=1; h<=12; h++){
bg_color=231+h;
putp(tparm(set_a_background, bg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
putp(exit_attribute_mode);
putchar('\n');
printf("%*s", (int)(columns-60)/2, "");
putp(tparm(set_a_foreground, 16));
for(h=13; h<=24; h++){
bg_color=231+h;
putp(tparm(set_a_background, bg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
bg_color=231;
putp(tparm(set_a_background, bg_color));
printf(" (15/231) ");
fflush(stdout);
putp(exit_attribute_mode);
putchar('\n');

return 0;
}


3. Re: Cores terminal Linux [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 05/05/2016 - 02:09h

Deve ser isto aqui:

* http://askubuntu.com/questions/558280/changing-colour-of-text-and-background-of-terminal
* http://askubuntu.com/questions/17299/what-do-the-different-colors-mean-in-the-terminal

----------------------------------------------------------------------------------------------------------------
# apt-get purge systemd (não é prá digitar isso!)

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden



4. Re: Cores terminal Linux [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 05/05/2016 - 11:03h

Parabéns, Paulo.
Isso vale um artigo.


5. Re: Cores terminal Linux [RESOLVIDO]

Ricardo Fabiano Silva
madrugada

(usa Gentoo)

Enviado em 05/05/2016 - 11:29h

izaias escreveu:

Parabéns, Paulo.
Isso vale um artigo.


Concordo. tive a ligeira impressão que o Paulo leciona linguagem C.
Parabéns!


6. Re: Cores terminal Linux [RESOLVIDO]

Leandro Cunha
Leandro_Cunha

(usa Debian)

Enviado em 05/05/2016 - 11:29h

paulo1205 escreveu:

Como você perguntou num fórum de programação em C voltada primeiramente para Linux, deixe eu responder como um programador em C no mundo UNIX.

Para manipular qualquer atributo do terminal, você deve usar os recursos da biblioteca de terminal (chamada “terminfo”, abreviação de “terminal information”, em alguns sistemas, e “termcap”, abreviação de “terminal capabilities”, em outros). Para tanto, seu programa em C deve incluir o cabeçalho <term.h> e, na hora de linkar o programa, você deve adicionar a biblioteca correspondente (flags “-ltinfo” ou “-ltermcap”, dependendo do sistema; o Linux usa a primeira).

A biblioteca de terminal usa uma interface única para diversos tipos de terminal, independentemente dos recursos que ele oferece. Se você faz o seu programa com essas interfaces, e calha de ter o seu programa executando num terminal que não suporta determinado recurso, ele simplesmente não vai ativar tal recurso, mas vai seguir executando.

Em muitos lugares, inclusive em várias postagens deste fórum, você vai encontrar gente indicando sequências de escape do padrão ANSI X3.64, que deveriam ser diretamente embutidas dentro do seu programa. Eu sou radicalmente contrário a esse uso porque, embora a grande maioria dos terminais do mundo UNIX (incluindo os emuladores de terminal, como xterm, gnome-terminal ou konsole, os consoles de texto do Linux e outros UNIXes que rodam em PCs, os gestores de janelas de texto, como screen e byobu etc.) sejam compatíveis com X3.64, não dá para assumir que essa compatibilidade será SEMPRE verdadeira. Aliás, é até muito comum encontrar terminais não compatíveis com ANSI nem qualquer outra coisa: basta pensar no Windows, cujo console de texto e emuladores de terminal não usam sequências de caracteres de controle, mas chamadas ao sistema operacional.

Quando eu comecei a mexer com UNIX, os terminais de texto da minha faculdade tinham emulação de dezenas de tipos de terminal diferentes, EXCETO ANSI X3.64 ou qualquer coisa dela derivada (como VT-100). Em terminais assim, aquelas sequências fixas embutidas no programa, além de não produzirem os efeitos desejados, tendem a produzir efeitos desagradáveis ou até mesmo nocivos. Se você usar terminfo ou termcap (inclusive para Windows), você pode ter a segurança de que se você solicitar um recurso que o terminal não suporte, não será gerado conteúdo destrutivo, e o pior que pode acontecer é algo não ficar na forma como você gostaria que ficasse.

No caso específico de cores, você deve chamar tparm(set_a_foreground, numero_da_cor) para obter a sequência correta que ajuste a cor de primeiro plano, e tparm(set_a_background, numero_da_cor) para a sequência que troca a cor de fundo. Se você passar um número de cor não suportado pelo terminal, a cor simplesmente não será trocada, e nada será enviado ou feito com o terminal em decorrência da tentativa de trocar a cor.

Eis um exemplo de programa que mexe com cores, que eu fiz há alguns anos, justamente para aprender a brincar com isso. Compile-o com o comando “gcc colormatrix.c -o colormatrix -ltinfo”. Na hora de rodar, experimente primeiro rodá-lo normalmente (e.g. “./colormatrix”, e depois veja quais as diferenças quando você altera o tipo do terminal (por exemplo: “env TERM=xterm-256color ./colormatrix”, “env TERM=xterm-16color ./colormatrix”, “env TERM=ansi ./colormatrix”, “env TERM=vt100 ./colormatrix”, “env TERM=vt100 ./colormatrix”, “env TERM=dumb ./colormatrix”).

// colomatrix.c
#include <term.h>
#include <stdio.h>
#include <unistd.h>


const char msg_8_colors[]="Tabela com 8 cores dos terminais compativeis com ANSI X3.64";
const char msg_8b_colors[]="Tabela com 8 cores dos terminais compativeis com ANSI X3.64 + opcao de bold";
const char msg_16_colors[]="Tabela com 16 cores do PC e/ou Xterm";
const char msg_256_colors[]="Tabela com 256 cores do Xterm (16 basicas acima, 216 RGB, 24 tons de cinza)";


int main(void){
int r, g, b, h;
int fg_color, bg_color;

setupterm(NULL, STDOUT_FILENO, NULL);

putp(exit_attribute_mode); /* limpa atributos de texto */
putp(clear_screen); /* limpa tela */
putp(tparm(cursor_address, 0, 0)); /* vai para 1ª linha, 1ª coluna */

/* ‘max_colors’, ‘columns’ e ‘lines’ são variáveis globais definidas pela biblioteca */
printf("Número máximo de cores: %d\n\n", max_colors);

printf("%*s%s\n\n", (int)(columns+1-sizeof msg_8_colors)/2, "", msg_8_colors);
printf("%*s", (int)(columns-24)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r;
fg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %1d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');

printf("\n\n%*s%s\n\n", (int)(columns+1-sizeof msg_8b_colors)/2, "", msg_8b_colors);
printf("%*s", (int)(columns-24)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r;
fg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %1d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
printf("\n%*s", (int)(columns-32)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
fg_color=b+2*g+4*r;
bg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" N%1d ", fg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
printf("\n%*s", (int)(columns-32)/2, "");
putp(enter_bold_mode);
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
fg_color=b+2*g+4*r;
bg_color=(r+b+g>=2? 0: 7);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" B%1d ", fg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');

printf("\n\n%*s%s\n\n", (int)(columns+1-sizeof msg_16_colors)/2, "", msg_16_colors);
for(h=0; h<=1; h++){
printf("%*s", (int)(columns-32)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r+8*h;
fg_color=(h+r+b+g>=2? 0: 15);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %2d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');
}

printf("\n\n%*s%s\n\n", (int)(columns+1-sizeof msg_256_colors)/2, "", msg_256_colors);
for(h=0; h<=1; h++){
printf("%*s", (int)(columns-40)/2, "");
for(r=0; r<=1; r++){
for(g=0; g<=1; g++){
for(b=0; b<=1; b++){
bg_color=b+2*g+4*r+8*h;
fg_color=(h+r+b+g>2? 0: 15);
putp(tparm(set_a_background, bg_color));
putp(tparm(set_a_foreground, fg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
}
}
putp(exit_attribute_mode);
putchar('\n');
}
for(r=0; r<6; r++){
for(g=0; g<6; g++){
if(!(g&1))
printf("%*s", (int)(columns-60)/2, "");
for(b=0; b<6; b++){
bg_color=16+36*r+6*g+b;
fg_color=(r+g+b>=6? 16: 231);
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
putp(exit_attribute_mode);
if(g&1)
putchar('\n');
}
}
printf("%*s", (int)(columns-60)/2-8, "");
bg_color=16;
fg_color=231;
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" (0/16) ");
fflush(stdout);
for(h=1; h<=12; h++){
bg_color=231+h;
fg_color=(h>12? 0: 15);
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
putp(exit_attribute_mode);
putchar('\n');
printf("%*s", (int)(columns-60)/2, "");
for(h=13; h<=24; h++){
bg_color=231+h;
fg_color=(h>12? 0: 15);
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" %3d ", bg_color);
fflush(stdout);
}
bg_color=231;
fg_color=16;
putp(tparm(set_a_foreground, fg_color));
putp(tparm(set_a_background, bg_color));
printf(" (15/231) ");
fflush(stdout);
putp(exit_attribute_mode);
putchar('\n');

return 0;
}


Muito útil essas informações, parabéns para você e obrigado pelas informações.


7. Re: Cores terminal Linux [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 06/05/2016 - 05:56h

Uma coisa que eu esqueci de comentar, e que talvez interesse a você tanto saber quanto experimentar, é a seguinte: diferentes terminais podem ter noções diferentes sobre cores. Por exemplo, a cor 3 pode ter aspecto mais de amarelo num terminal, e mais de marrom em outro. Alguns terminais até permitem que o usuário escolha os tons de cada uma das primeiras 8 ou 16 cores.

Outro fator é a interação das cores básicas (0-7) com atributos, particularmente o atributo bold). Em alguns terminais, usar bold pode apenas deixar a letra mais espessa, sem alterar sua cor, ao passo que outros podem optar por apenas deixar a letra numa cor mais brilhante, sem mexer na espessura, e outros ainda podem mudar tanto a cor como a espessura. E alguns podem permitir ao usuário definir qual o comportamento desejado.

A maioria dos emuladores de terminal do X11 suporta, hoje em dia, 256 cores mas, frequentemente, mesmo tais terminais se identificam somente como xterm, e não como xterm-256color, e isso faz com que muitas aplicações se limitem apenas às primeiras oito cores, ou talvez dezesseis (oito cores básicas, mais a variação do atributo bold). Isso é mais um empecilho para você usar logo de cara 256 cores em todas as suas aplicações (assumindo que você sempre vá rodar suas aplicações de texto num emulador, nunca no próprio console de texto), mas tem uma justificativa: compatibilidade com sistemas antigos ou de código fechado, cujos xterms podem não possuir as mesmas opções de cores, e que podem também não possuir uma definição para um terminal chamado “xterm-256color”.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts