Padrões para códigos de escape ANSI


Olá! Hoje quero falar sobre códigos de escape ANSI.

Por muito tempo eu estava vagamente ciente dos códigos de escape ANSI (“é assim que você deixa o texto vermelho no terminal e outras coisas”), mas não tinha uma compreensão real de onde eles deveriam ser definidos ou se havia ou não padrões para eles. Eu apenas tive uma sensação vaga de “há dragões” ao redor deles. Ao aprender sobre o terminal este ano, aprendi que:

  1. Os códigos de escape ANSI são responsáveis ​​por muitas melhorias de usabilidade no terminal (você sabia que existe uma maneira de copiar para a área de transferência do sistema quando conectado por SSH em uma máquina remota?? É um código de escape chamado OSC 52!)
  2. Eles não são completamente padronizados e, por isso, nem sempre funcionam de maneira confiável. E como eles também são invisíveis, é extremamente frustrante solucionar problemas de código de escape.

Então, eu queria montar uma lista de alguns padrões que existem em torno dos códigos de escape, porque quero saber se eles ter sentir-se pouco confiável e frustrante, ou se houver um futuro em que todos possamos confiar neles com mais confiança.

o que é um código de escape?

Você já pressionou a tecla de seta para a esquerda em seu terminal e viu ^((D? Esse é um código de escape! É chamado de “código de escape” porque o primeiro caractere é o caractere de “escape”, que geralmente é escrito como ESC, x1b, E,
33ou ^(.

Os códigos de escape são a forma como o emulador de terminal comunica vários tipos de informações (cores, movimento do mouse, etc.) com programas em execução no terminal. Existem dois tipos de códigos de escape:

  1. códigos de entrada que seu emulador de terminal envia para pressionamentos de teclas ou movimentos do mouse que não cabem no Unicode. Por exemplo, “tecla de seta para a esquerda” é
    ESC(D“Ctrl+seta para esquerda” pode ser ESC(1;5De clicar com o mouse pode ser algo como ESC(M :3.
  2. códigos de saída quais programas podem imprimir texto colorido, mover o cursor, limpar a tela, ocultar o cursor, copiar texto para a área de transferência, ativar relatórios do mouse, definir o título da janela, etc.

Agora vamos falar sobre padrões!

ECMA-48

O primeiro padrão que encontrei relacionado a códigos de escape foi o ECMA-48, publicado originalmente em 1976.

ECMA-48 faz duas coisas:

  1. Defina alguns gerais formatos para códigos de escape (como códigos “CSI”, que são
    ESC( + alguma coisa e códigos “OSC”, que são ESC) + alguma coisa)
  2. Defina alguns códigos de escape específicos, como “mover o cursor para a esquerda”
    ESC(Dou “tornar o texto vermelho” é ESC(31m. Na especificação, o “cursor para a esquerda” é chamado CURSOR LEFT e aquele para mudar as cores é chamado
    SELECT GRAPHIC RENDITION.

Os formatos são extensíveis, portanto há espaço para que outros definam mais códigos de escape no futuro. Muitos códigos de escape populares hoje em dia não são definidos no ECMA-48: por exemplo, é bastante comum que aplicativos de terminal (como vim, htop ou tmux) suportem o uso do mouse, mas o ECMA-48 não define códigos de escape para o mouse.

sequências de controle xterm

Existem vários códigos de escape que não estão definidos no ECMA-48, por exemplo:

  • habilitando relatórios do mouse (onde você clicou no seu terminal?)
  • colar entre colchetes (você colou esse texto ou digitou?)
  • OSC 52 (que aplicativos de terminal podem usar para copiar texto para a área de transferência do sistema)

Acredito (corrija-me se estiver errado!) que estes e alguns outros vieram do xterm, estão documentados em XTerm Control Sequences e foram amplamente implementados por outros emuladores de terminal.

Esta lista de “o que o xterm suporta” não é exatamente um padrão, mas o xterm é extremamente influente e por isso parece um documento importante.

informações do termo

Na década de 80 (e até certo ponto hoje, mas meu entendimento é que foi MUITO mais dramático na década de 80) havia uma enorme variação nos códigos de escape que os terminais realmente suportavam.

Para lidar com isso, existe um banco de dados de códigos de escape para vários terminais chamado “terminfo”.

Parece que o padrão para terminfo é chamado X/Open Curses, embora você precise criar uma conta para visualizar esse padrão por algum motivo. Ele define o formato do banco de dados, bem como uma interface de biblioteca C (“curses”) para acessar o banco de dados.

Por exemplo, você pode executar este snippet bash para ver todos os códigos de escape possíveis para “limpar tela” para todos os diferentes terminais que seu sistema conhece:

for term in $(toe -a | awk '{print $1}')
do
  echo $term
  infocmp -1 -T "$term" 2>/dev/null | grep 'clear=" | sed "s/clear=//g;s/,//g'
done

No meu sistema (e provavelmente em todos os sistemas que já usei?), o banco de dados terminfo é gerenciado pelo ncurses.

os programas devem usar terminfo?

Acho interessante que existam duas abordagens principais que os aplicativos adotam para lidar com códigos de escape ANSI:

  1. Use o banco de dados terminfo para descobrir quais códigos de escape usar, dependendo do que está no TERM variável de ambiente. Peixe faz isso, por exemplo.
  2. Identifique um “único conjunto comum” de códigos de escape que funcione em emuladores de terminal “suficientes” e apenas codifique-os.

Alguns exemplos de programas/bibliotecas que adotam a abordagem nº 2 (“não use terminfo”) incluem:

Fiquei curioso para saber por que as pessoas podem estar se afastando do terminfo e achei este discurso muito interessante e extremamente detalhado sobre o terminfo de um dos mantenedores do peixe, que argumenta que:

(os autores do terminfo) realizaram muitos trabalhos que, na época, foram extremamente importantes e úteis. O que quero dizer é que não é mais.

Não vou fazer justiça então não vou resumir, acho que vale a pena ler.

existe um “conjunto único comum” de códigos de escape?

Eu estava falando sobre a ideia de que você pode usar um “conjunto comum” de códigos de escape que funcionarão para a maioria das pessoas. Mas o que é esse conjunto? Existe algum acordo?

Eu realmente não sei a resposta para isso, mas ao fazer algumas leituras, parece que é uma combinação de:

  • Os códigos suportados pelo VT100 (embora alguns não sejam relevantes em terminais modernos)
  • o que há no ECMA-48 (que acho que também contém algumas coisas que não são mais relevantes)
  • O que o xterm suporta (embora eu ache que nem tudo o que está lá é amplamente suportado o suficiente)

e talvez, em última análise, “identifique os emuladores de terminal que você acha que seus usuários usarão com mais frequência e teste-os”, da mesma forma que os desenvolvedores web fazem ao decidir quais recursos CSS podem ser usados.

Não creio que existam recursos como Posso usar…? ou Linha de base para o terminal. (em teoria, terminfo deveria ser o “canius” para o terminal, mas parece que muitas vezes leva mais de 10 anos para adicionar novos recursos ao terminal quando as pessoas os inventam, o que o torna muito limitado)

alguns motivos para usar terminfo

Também perguntei no Mastodon por que as pessoas consideraram o terminfo valioso em 2025 e obtive alguns motivos que faziam sentido para mim:

  • algumas pessoas esperam poder usar o TERM variável de ambiente para controlar como os programas se comportam (por exemplo, com TERM=dumb), e não há um padrão de como isso deveria funcionar em um mundo de informações pós-termo
  • mesmo que haja menos variação entre emuladores de terminal do que havia nos anos 80, a variação está longe de ser zero: existem terminais gráficos, o console framebuffer do Linux, a situação em que você se encontra ao se conectar a um servidor por meio de seu console serial, modo shell Emacs e provavelmente mais que estou perdendo
  • não existe um padrão para o que é o “conjunto único comum” de códigos de escape e, às vezes, os programas usam códigos de escape que não são amplamente suportados o suficiente

terminfo e detecção de agente de usuário

A maneira como ncurses usa o TERM variável de ambiente para decidir quais códigos de escape usar me lembra como os servidores da web costumavam às vezes usar o agente do usuário do navegador para decidir qual versão de um site servir.

Também parece que teve alguns dos mesmos resultados – a forma como o iTerm2 se reporta como sendo “xterm-256color” é semelhante a como o agente de usuário do Safari é “Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_4) AppleWebKit/605.1.15 (KHTML, como Gecko) Versão/18.3 Safari/605.1.15”. Em ambos os casos, o emulador de terminal/navegador acaba alterando seu agente de usuário para contornar a detecção de agente de usuário que não está funcionando bem.

Na web, acabamos decidindo que a detecção de agente de usuário não era uma boa prática e, em vez disso, nos concentramos na padronização para que possamos servir o mesmo HTML/CSS para todos os navegadores. Não sei se a mesma abordagem será o futuro no terminal – penso que o panorama do terminal hoje é muito mais fragmentado do que a web alguma vez foi, além de ser muito menos bem financiado.

mais alguns documentos/padrões

Mais alguns documentos e padrões relacionados a códigos de escape, sem ordem específica:

por que eu acho isso interessante

Às vezes vejo pessoas dizendo que o terminal unix está “desatualizado”, e como adoro tanto o terminal, estou sempre curioso para saber quais mudanças incrementais podem fazer com que ele pareça menos “desatualizado”.

Talvez se tivéssemos um cenário de padrões mais claro (como fazemos na web!), seria mais fácil para os desenvolvedores de emuladores de terminal criarem novos recursos e para os autores de aplicativos de terminal adotarem esses recursos com mais confiança, para que todos possamos nos beneficiar deles e ter uma experiência mais rica no terminal.

Obviamente, padronizar códigos de escape ANSI não é fácil (ECMA-48 foi publicado pela primeira vez há quase 50 anos e ainda não chegamos lá!). Eu nem sei quais são todos os desafios. Mas a situação com HTML/CSS/JS também costumava ser extremamente ruim e agora está MUITO melhor, então talvez haja esperança.



Source link

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

Botão Voltar ao Topo