Leitura adicional

Leitura adicional

Quando você executa cal no Linux, a saída do mês atual reverterá o destaque do vídeo para o dia atual. Quando envio essa saída para hexdump -c, obtenho alguns resultados interessantes:

0000000               N   o   v   e   m   b   e   r       2   0   1   6
0000010                          \n   S   u       M   o       T   u    
0000020   W   e       T   h       F   r       S   a          \n        
0000030                       1           2       _  \b       _  \b   3
0000040           4           5          \n       6           7        
0000050   8           9       1   0       1   1       1   2          \n
0000060   1   3       1   4       1   5       1   6       1   7       1
0000070   8       1   9          \n   2   0       2   1       2   2    
0000080   2   3       2   4       2   5       2   6          \n   2   7
0000090       2   8       2   9       3   0                            
00000a0                  \n                                            
00000b0                                              \n                
00000bc

Como você pode ver, há uma sequência invisível sendo impressa de _\b _\b antes do '3' que está destacado hoje. _ sendo sublinhado (5F em hexadecimal ASCII) e \b sendo Ctrl-H ou 08 em hexadecimal ASCII. O que é isso? Eu sei que existem muitos códigos de terminal obscuros, mas esperaria que usasse algo mais padrão como \e[7m. O que é ainda mais estranho é que não consigo reproduzir o mesmo comportamento de cal imprimindo os mesmos caracteres usando funções printf padrão como um destes comandos:

/usr/bin/printf "1 2 _\b _\b3 4 5\n"
/usr/bin/printf "1 2 _^H _^H3 4 5\n"

Onde ^H é feito pressionando Ctrl-V Ctrl-H. Mas nenhum deles produz a mesma saída de vídeo inversa que o cal. Eu até tentei escrever um pequeno programa em C para fazer isso também. Eu também tentei com echo -e. O interessante é que embora não inverta o vídeo no terminal, se eu canalizar a saída de less -R, ele muda sua cor para amarelo e sublinha. Em outros terminais eu tentei apenas sublinhar. Quase parece exagerado, mas se eu usar um caractere diferente de _ não funciona, o que me faz pensar que _\b é uma única sequência de código. E como o vídeo desse personagem é invertido?

Alguma ideia sobre isso?

A página de manual diz que a saída de cal deve ser uma versão bit a bit compatível com o comando cal original do Unix. Portanto, só posso presumir que se trata de algum código antigo.

Responder1

Quase parece exagerado

É exatamente isso. Como discutido emPor que existem 11 tabs em um console de 80 colunas?, ajuda pensar na ação das máquinas de escrever mecânicas quando se trata de terminais Unix. Neste caso, a sequência _ BS (o caractere backspace) antes de um caractere é uma convenção que serve para indicar o sublinhado daquele caractere, pois em alguns terminais é assim que se sublinha o texto. Uma sequência de controle alternativa é BS _após o caractere. Nos terminais originais, não importava o que ultrapassasse o quê, é claro. Nos terminais de vídeo contemporâneos, o último caractere escrito “ganha”, apagando os dados anteriores. Portanto, o _ B.S. <personagem>a ordem é preferida.

FreeBSD ncal, que é o que este programa é, possui dois modos de operação quando se trata de destaque.

  • Se sua saída for um terminal, ele procura as sequências soe separa o tipo de terminal atual no banco de dados termcap e as emite em ambos os lados do texto destacado. (Na verdade, há um bug no código que faz isso, relacionado a um buffer na pilha que sai do escopo e seu conteúdo é usado posteriormente, que ninguém parece ter detectado.)
  • Caso sua saída não seja um terminal, ele emite o texto com cada caractere a ser destacado precedido de uma _sequência BS.

Você não pode replicar isso emitindo uma _sequência BS para o seu terminal, a menos que (é claro) o seu terminal seja um dos terminais onde é assim que se sublinha as coisas. Este não é o caso dos emuladores de terminal e quase certamente não é o caso de quaisquer terminais ou emuladores de terminal que você esteja usando aqui.

Você pode, no entanto,filtrotexto que usa esta convenção, através do ulprograma, que reconhece esta e várias outras convenções semelhantes às de máquinas de escrever e as traduz para quaisquer que sejam as sequências de controle do terminal, procurando-as no banco de dados termcap. Você também pode filtrar as saídas de seus printfcomandos ul.

Em outros terminais eu tentei apenas sublinhar.

Ironicamente, filtrar a saída do modo não terminal por ncalmeio do ulprograma é, na verdade, um pouco superior a permitir ncala gravação das próprias sequências de controle do terminal. Considerando que ncalusa o terminalse destacaremmodo, ultentará usar o real do terminalsublinhadomodo (se houver) ao traduzir a _sequência BS. Como explica o manual do termcap, o modo de destaque pode ser o que for adequado ao terminal (incluindo negrito, vídeo reverso ou cores) e não é necessariamente sublinhado. Em um de seus terminais, é claramente uma combinação de sublinhado e mudança de cor.

Além disso, ultambém funciona com terminais que não possuem sequências de início/fim sublinhadas, mas que possuem sequências de últimos caracteres sublinhadas. Ironicamente, ulvai funcionar se o seu terminalrealmente éaquele que sublinha ter BS _depois de cada personagem, mas ncalnão vai dar conta.

E, claro, ulnão possui ncalo bug de manipulação de buffer. ☺

Se eu canalizar a saída para less -R, ela mudará sua cor para amarelo e a sublinhará.

Como você percebeu, o lessprograma entende _as sequências BS e as trata da mesma forma que o ulprograma. Não é completamente a mesma coisa. ulpode lidar com sequências envolvendo _caracteres múltiplos e BS e também pode lidar com sequências semelhantes para negrito. lessnão pode. Compare o que você vê destes dois:

  • /usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4. \b\b\b45 6\n" | ul
  • /usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4. \b\b\b45 6\n" | menos

de volta aos bons velhos tempos

Infelizmente, estes ainda são “os bons e velhos tempos”. Não deixe que as pessoas o enganem fazendo-o acreditar que isso raramente é usado hoje em dia.

Não está no manual, mas o código-fonte ulaponta que está tentando implementar o processamento da sequência de controle de um Teletype Model 37 porque "é isso que nroffproduz". O substituto GNU para o nroffprograma Unix original, escrito muito depois de os terminais terem ganhado recursos sofisticados como cores, negrito e itálico, é capaz de gerarECMA-48sequências de controle para cores, negrito e itálico. Na verdade faz issono caso normal.

nroff, e seu substituto GNU, são usados ​​para formatar páginas de manual para exibição em seu terminal. Infelizmente, e ironicamente, cerca de 10 anos depois de ter sido escrito, as pessoas começaram a prejudicar a ferramenta GNU para que ela gerasse as antigas sequências do Teletype Model 37 de 1968, em vez das "novas" sequências de controle ECMA-48 de 1976 (sic!). Eles maninvocaram groffopções que modificaram seu comportamento padrão e adicionaram arquivos não documentados que forçaram uma saída ditroff extra.

Cada vez que você lê uma página de manual em seu terminal, o sistema manual está em execução, groffconvertendo obedientemente o texto fonte do manual em um fluxo de caracteres de saída com essas antigas sequências de controle do Teletype Model 37, que lessestão moresendo convertidas nas sequências de controle do seu terminal.

Leitura adicional

Responder2

Ctrl-Hé backspace, move o cursor um passo para a esquerda. Enviar um sublinhado, um backspace e algum outro caractere era a maneira de sublinhar algo em um terminal impresso ("papel") nos bons e velhos tempos. Isso foi usado para destacar o dia atual na saída do arquivo cal.

Meu calprograma, quando executado, konsolenão gera essa sequência. Se eu executar script -c cale examinar o typescriptarquivo resultante, posso ver que o programa cal usa a sequência de escape <esc>[7mpara mudar para o modo de vídeo inverso.

informação relacionada