coluna do aurelio 11: caracteres de controle (não fuja, domine-os)

https://aurelio.net/doc/coluna

Escrito por Aurelio Jargas em 2001-08-27

caracteres de controle para formatação de texto e movimentação do cursor: um assunto salgado, mas que fascina e apaixona quanto mais você aprende e mexe. mas qual a graça de ficar posicionando o cursor na tela? toda! o limite é sua imaginação, pode ser útil para fazer desenhos, animações, barra de status, interfaces que se atualizam, ...

estes comandos são chamados de seqüências de escape, e veremos o padrão ANSI X3.64. o nome é apropriado, pois todas as seqüências são precedidas pelo caractere ESC da tabela ASCII (código 033 octal).

as seqüências funcionam em placas monocromáticas e coloridas, então até naquela velharia de tela verde você pode brincar. os comandos devem ser enviados diretamente ao terminal, ou seja, devem ser ecoados na tela. para isso você pode usar qualquer um dos vários sabores de print e printf existentes, mas nosso bom e velho echo também dá conta do serviço.

as seqüências são diferenciadas entre si por caracteres comuns, sendo o ESC inicial o único problemático para ecoar. pode-se colocá-lo literal, apertando ctrl+v, esc (aparece ^[), ou referenciá-lo por seu código octal, usando a opção -e do echo. como a quebra de linha geralmente não é desejada quando estamos mandando comandos para a tela, a opção -n também é necessária.

todas as seqüências que veremos começam com um ESC seguido de um colchete, então ESC[ é o nosso início padrão de seqüência. opa! temos uma exceção. o comando para limpar a tela, similar ao clear é ESCc:

prompt$ echo -ne '\033c'

então pra começar, vamos ver como definir cores para as letras e seus fundos? esta seqüência é geralmente a mais utilizada, porém possui diversos parâmetros, e merece atenção especial. você sempre quis saber como mostrar um texto colorido e não tinha a quem perguntar ou achava que era muito complicado? acompanhe!

o formato do comando é ESC[n1;n2;...m, ou seja, abre com o padrão esc-colchete e fecha com a letra eme. no meio temos números separados por ponto-e-vírgula. o padrão caso nenhum número seja informado é zero. vamos aos significados dos números:

 0  desliga tudo (volta ao normal)
 1  cor brilhante
 5  pisca-pisca
 7  vídeo reverso (inverte letra e fundo)
30  texto preto (cinza)          40 fundo preto (cinza)
31  texto vermelho               41 fundo vermelho
32  texto verde                  42 fundo verde
33  texto marrom (amarelo)       43 fundo marrom (amarelo)
34  texto azul                   44 fundo azul
35  texto roxo                   45 fundo roxo
36  texto ciano                  46 fundo ciano
37  texto cinza (branco)         47 fundo cinza (branco)

os números são lidos de forma seqüencial e adicional, então 44;31;1;5 é: fundo azul, com letra vermelha e brilhante (clara), e ainda piscando, confira:

prompt$ echo -e '\033[44;31;1;5m azul e vermelho \033[m'

note que a cor brilhante geralmente indica o vermelho claro, verde claro, e assim vai. as exceções são o marrom que vira amarelo, o preto que vira cinza e o cinza que vira branco.

aqui vai um script superútil para lhe mostrar todas as combinações possíveis com os códigos de cores. guarde e use!

#!/bin/bash
# cores.sh - mostra todas as cores do console

for letra in 0 1 2 3 4 5 6 7; do
 for bold in '' ';1'; do
   for fundo in 0 1 2 3 4 5 6 7; do
     seq="4$fundo;3$letra"
     echo -ne "\033[$seq${bold}m $seq${bold:-  } \033[m"
   done; echo
 done
done

agora que já sabemos como colorir um texto, vamos ver como colocá-lo exatamente onde queremos na tela. o formato padrão dos comandos de movimentação é ESC[<quantidade><comando>. vamos começar com os comandos de movimentação simples, os mais comuns:

comando   padrão   move o cursor...
--------+--------+------------------------------------------
ESC[nA    n=1      n linhas para cima, na mesma coluna
ESC[nB    n=1      n linhas para baixo, na mesma coluna
ESC[nC    n=1      n colunas para a direita, na mesma linha
ESC[nD    n=1      n colunas para a esquerda, na mesma linha
ESC[nE    n=1      n linhas para baixo, na coluna 1
ESC[nF    n=1      n linhas para cima, na coluna 1
ESC[nG    n=1      para a coluna n da linha atual
ESC[n;mH  n=1,m=1  para a coluna m da linha n

é fácil, basta ecoar o comando e o cursor vai dar o pulo, por exemplo, ESC[5E pula para o começo da 5ª linha abaixo da posição atual.

bem, para ficar mais visual o que cada comando desses faz, aqui vai um "gráfico" de exemplo de movimentação do cursor com os comandos sendo executados com seus valores padrão (n=1,m=1) à partir da posição marcada pelo ponto, que está na linha 4 coluna 7:

 123456789
+----------
1|H
2|
3|F     A
4|G    D.C
5|E     B
6|

e como um exemplo prático, este comando gera o conteúdo do gráfico anterior:

echo -e '\033c\033[HH\033[4;7H.C\033[3DD\033[AA\033[GF\033[EG\033[EE\033[7GB'

além destes, temos outros comandos de movimentação e outros para apagar trechos de texto, confira:

comando   padrão   ação
--------+--------+----------------------------------------------
ESC[nJ    n=0      (n=0) apaga até o fim da tela
                   (n=1) apaga até o começo da tela
                   (n=2) apaga a tela toda
--------+--------+----------------------------------------------
ESC[nK    n=0      (n=0) apaga até o fim da linha
                   (n=1) apaga até o começo da linha
                   (n=2) apaga a linha toda
--------+--------+----------------------------------------------
ESC[nM    n=1      apaga n linhas para baixo
ESC[nP    n=1      apaga n caracteres à direita
ESC[nX    n=1      limpa n caracteres à direita (coloca espaços)
--------+--------+----------------------------------------------
ESC[n@    n=1      insere n espaços em branco
ESC[nL    n=1      insere n linhas em branco
--------+--------+----------------------------------------------
ESC[nS    n=1      move a tela n linhas para cima
ESC[nT    n=1      move a tela n linhas para baixo

bem, as tabelas estão aí e você já sabe como ecoar os comandos na tela. agora é só soltar a imaginação e brincar com os caracteres. para fechar, dois dos exemplos mais clássicos de posicionamento de cursor, a tradicional barra de status, que usa pulos, inserção e apagamento:

for i in 1 2 3 4 5 6 7 8 9; do
  echo -ne "\033[G\033[@#\033[11G\033[0K$i"
  sleep 1
done; echo

e é claro, a clássica hélice ASCII:

while :; do for a in / - \\ \|; do echo -ne "\033[D$a"; done; done

vale lembrar que alguns comandos como o tput ou bibliotecas como ncurses visam facilitar a tarefa de posicionamento de texto e desenho de caixas e botões, com funções já prontas para fazer isso. mas que graça isso tem se você pode fazer tudo na mão e reinventar a roda? &:)