As cores do terminal são complicadas
(jvns.ca)- Os problemas com cores no terminal têm menos a ver com gosto pessoal e mais com a falta de padrão e diferenças de implementação, então a saída do mesmo comando pode ficar difícil de ler dependendo da combinação de terminal, tema e app
- As 16 cores ANSI padrão, 256 cores e cores hex de 24 bits são usadas juntas, mas a cor real exibida para cada número pode variar conforme o emulador de terminal
- Casos como texto azul em fundo preto, amarelo claro em fundo branco, o mapeamento de cinzas no Solarized e o fundo do
ngrokmostram conflitos de contraste quando as suposições do programa não batem com o tema do usuário - As soluções se dividem em várias camadas, como redefinir a paleta,
base16-shell,LS_COLORS,NO_COLOR=true,--color=always,unbuffere o suporte a cores de 24 bits no Vim/Neovim - O recurso de minimum contrast no iTerm2, tabby, kitty, Ghostty e Windows Terminal não resolve tudo, mas reduz o risco de saídas ilegíveis
Cores ANSI e diferenças entre terminais
- O terminal normalmente tem 16 cores ANSI, compostas por preto, vermelho, verde, amarelo, azul, magenta, ciano e branco, além de uma versão clara de cada uma
- Os programas definem cores emitindo códigos de escape ANSI
- Por exemplo, dá para definir o número da cor de primeiro plano com algo como
\033[38;5;{num}m
- Por exemplo, dá para definir o número da cor de primeiro plano com algo como
- O problema é que não existe um padrão consistente para qual cor hex real corresponde a cada número ANSI
- Cada emulador de terminal escolhe suas próprias cores
- Até a tabela de cores dos códigos de escape ANSI na Wikipedia mostra grandes diferenças entre implementações
- Por causa disso, o azul que o
lsusa para diretórios pode ficar difícil de ver sobre fundo preto - A combinação de amarelo claro com fundo branco também é quase ilegível, e problemas parecidos podem acontecer com outras cores, como verde claro
Como redefinir a paleta de cores
- Se você não gostar das cores ANSI padrão ou tiver problemas de contraste, uma opção é redefinir a paleta
-
Configuração no emulador de terminal
- A maioria dos emuladores de terminal modernos oferece alguma forma de redefinir as cores
- Alguns já incluem temas prontos
- Emuladores mais populares podem oferecer mais opções de tema
-
Configuração via script de shell
- Também dá para mudar a paleta do emulador de terminal emitindo códigos de escape ANSI
- O script Solarized Light do base16-shell usa convenções de códigos de escape específicas para vários terminais
- O script tenta escolher o estilo de código de escape adequado com base na variável de ambiente
TERM - A abordagem com script de shell facilita manter a mesma configuração de cores mesmo ao trocar de emulador de terminal
- Mas nem todo emulador de terminal suporta esse tipo de mudança de paleta e, mesmo quando suporta, os resultados podem variar um pouco
256 cores, cores de 24 bits e temas por ferramenta
- Muitos terminais suportam 3 formas de definir cor
- 16 cores ANSI
- 256 cores expandidas
- Cores hex de 24 bits como
#ffea03
- O
fdusa códigos de escape como^[[38;5;48mna saída para definir a cor de primeiro plano 48- Essa cor pode parecer um tom de lima que não existe na tabela normal de cores do terminal
- O contraste com a paleta em uso pode ser ruim
- O
batusa cores de forma parecida, mas a saída padrão parece ter sido pensada para funcionar com vários temas de terminal - Algumas ferramentas de terminal mais modernas, como
fd,batedelta, suportam temas personalizados arbitrários- O tema padrão pode conflitar com o fundo do terminal
- Em compensação, isso permite controlar o tema da saída com mais precisão do que escolher apenas entre as 16 cores ANSI
- Com
bat --theme ansi, obatpassa a usar as cores ANSI definidas na paleta normal do terminal
Conflitos com Solarized e base16
- O Solarized Light pode mostrar mapeamentos diferentes para cores bright dependendo da implementação
- O tema Solarized Light padrão do iTerm mapeia as cores 9 a 14 — isto é, “bright blue”, “bright red” etc. — para tons de cinza, como no design original do Solarized
- Se o
lsusar cores bright para diretórios e executáveis, eles podem aparecer em cinza
- Se o
- O base16 Solarized Light pode ser usado em uma variação que mantém as cores bright como cores reais, e não cinza
- Essa diferença parece vir do fato de o Solarized original ter sido projetado para permitir que o esquema de cores do Vim usasse cinzas
- O
base16-shelldefine as cores 16 a 21 para tentar fornecer cores extras aobase16-vim- Se o
ngroktentar definir o fundo como a cor 16, “black”, e essa cor tiver sido remapeada para um laranja brilhante, o fundo fica muito estranho - Esse tipo de conflito aparece com facilidade quando o programa define uma cor de fundo ANSI e o usuário remapeia essa cor para outro significado
- Se o
Reduzindo problemas de contraste com minimum contrast
- Alguns terminais oferecem o recurso de minimum contrast, que ajusta automaticamente as cores quando o contraste entre primeiro plano e fundo não é suficiente
- iTerm2, tabby, kitty com text_fg_override_threshold, Ghostty e Windows Terminal oferecem esse recurso
- No iTerm, definir o minimum contrast como 40 já torna mais legíveis saídas difíceis de ler, como no conflito de fundo do
ngrok - Quando a configuração de cores está ruim ou há conflito entre programa e tema, o minimum contrast é uma proteção prática para reduzir problemas acidentais de legibilidade
TERM, pipes e desativação de cores
- Se o sistema acessado por SSH não suportar o valor local da variável de ambiente
TERM, as cores podem não funcionar direito - O sistema usa o banco de dados
terminfo, e se o valor deTERMnão existir nesse banco, fica difícil saber como emitir cores corretamente para aquele terminal - Não houve um ambiente reproduzível, mas uma resposta no Stack Overflow sugere usar algo como
TERM=xterm sshem vez de apenasssh - Ao conectar comandos com pipes, as cores às vezes são desativadas
fd | lesspode sair sem cores- Em geral, isso é útil quando a saída vai para ferramentas como
grep, já que o texto puro sem códigos de escape costuma ser preferível
- Se você quiser manter as cores, pode usar
unbuffer fd | less -r- O
unbufferabre um tty para que o comando pense que está escrevendo em um TTY - Isso também resolve problemas de buffering na saída quando ela vai para um pipe
- O
- Alguns comandos, como o
fd, também permitem forçar a cor com a flag--color=always
Como desativar ou mudar as cores do ls
- Alguns usuários não querem a saída colorida do
ls- porque o azul é difícil de ler em fundo preto
- porque não querem ajustar a paleta do terminal
- ou porque a cor em si pode não ajudar
- Há várias opções
- Dá para desligar as cores com
ls --color=never - Dá para personalizar as cores usadas pelo
lscom a variável de ambienteLS_COLORS - Alguns programas suportam
NO_COLOR=true, e há uma lista em no-color.org
- Dá para desligar as cores com
- Por exemplo, com
LS_COLORS="fi=0:di=0:ln=0:pi=0:so=0:bd=0:cd=0:or=0:ex=0" ls, é possível definir o estilo de cor de vários tipos de arquivo como 0
Mudanças no Vim e no Neovim
- Configurar cores no Vim já foi muito problemático porque era preciso alinhar a paleta do terminal com o esquema de cores do Vim
- Há basicamente 2 formas de definir esquemas de cores do Vim dentro do terminal
- Mapear classes de cor do Vim para números de cores ANSI
- Fazer o esquema de cores usar diretamente cores hex de 24 bits como
#faea99
- Há 20 anos, terminais com suporte a cores hex de 24 bits não eram comuns, e o Vim também não suportava cores de 24 bits no terminal
- O Vim adicionou suporte a cores de 24 bits em 2016
- O Neovim 0.10 foi lançado em maio de 2024 e, em terminais com suporte a cores de 24 bits, o
termguicolorsagora vem ativado por padrão - Se você não pretende usar em 2024 um terminal sem suporte a 24 bits, deixa de existir a obrigação de sincronizar manualmente a paleta do terminal com o esquema de cores do Vim
- Com isso, o
base16-shellpassa a precisar menos daquela configuração especial das cores 16 a 21 para integração com o Vim- Remover essa parte ajuda a evitar conflitos como o fundo laranja do
ngrok
- Remover essa parte ajuda a evitar conflitos como o fundo laranja do
Experiência com base16 e limitações
- Usar base16-shell junto com base16-vim facilita alinhar as cores do terminal e do Vim
- A configuração pode ser feita adicionando algumas linhas ao setup do fish e mais algumas linhas ao
.vimrc - O base16 não é ideal para todo mundo
- O número de temas embutidos é limitado, e você pode não gostar de nenhum
- Os temas Solarized do base16 definem as cores ANSI bright como iguais às cores normais, o que pode ser um problema em casos em que elas deveriam ser diferentes
- A abordagem de definir as cores 16 a 21 para oferecer mais cores ao
base16-vimpode ser desnecessária em ambientes que só usam terminais com suporte a 24 bits - A definição das cores 16 a 21 pode causar problemas em terminais que não suportam 256 cores, como o terminal framebuffer do Linux
- Existe um fork comunitário do base16 chamado tinted-theming
Ferramentas para esquemas de cores e temas populares
- rootloops.sh é uma ferramenta para gerar esquemas de cores
- Como leitura complementar, há o texto “let’s create a terminal color scheme”
- Esquemas de cores populares mencionados em respostas no Mastodon incluem
Problemas que ainda continuam
- Pontos de encontro entre vários programas, como a combinação de
tmux, SSH e Vim, ainda podem gerar problemas extras de cor - Escolher um bom esquema de cores em si também é difícil
- Usuários com daltonismo podem ter dificuldade para encontrar uma paleta adequada
- Se a cor de fundo for muito parecida com a do cursor ou da seleção, fica difícil localizar a posição
- É difícil encontrar cores que funcionem bem em todos os programas, e conflitos como o do
ngrokpodem acontecer
- Programas que esperam uma aparência “clássica” específica baseada nas cores ANSI padrão, como Nethack ou Midnight Commander, podem parecer estranhos com temas como Solarized
- Uma forma de lidar com isso é trocar a paleta ANSI logo antes de executar o programa
- Por exemplo, antes de abrir o Nethack, você pode remapear o amarelo para um amarelo mais brilhante
- Para quem só quer que as cores funcionem sem esforço, muita configuração manual é um peso, então valores padrão razoáveis e recursos como minimum contrast são importantes
1 comentários
Opiniões no Hacker News
Passei por todos esses problemas, e muitos outros, tentando criar corretamente um tema de cores claro para o sistema, e duas coisas em especial foram interessantes
Em retrospecto parece óbvio, mas me surpreendeu como temas claros parecem variar de forma muito mais sutil do que temas escuros quando a tela muda. Configurações de hardware e software realmente criam diferenças na saída de cores, mas mudanças centradas em áreas claras são percebidas de forma muito mais intensa do que mudanças em áreas escuras
Além disso, às vezes é preciso descer para ambientes com suporte limitado a fontes e cores sofisticadas, como o console do Linux ou do BSD; aí
fdouexa/lsd/whateverpodem ficar incômodos ou até inutilizáveis, especialmente se você tiver mapeado este último parals. Depois de muito bater cabeça, configurei o fbterm para ter recursos de terminal decentes mesmo sem X, mas o fbterm também tem seus próprios problemas. Ao configurar a paleta de cores do Vim, é preciso preparar um tema alternativo para consoles com poucos recursos, ou então praticar bastante para digitar comandos do Vim sem olhar :DEdição: não é para trabalho sério, mas uma tela estilizada do fbterm mostrando o que dá para fazer mesmo sem X: https://i.imgur.com/RbDRgtD.png
Por isso, ao ajustar a exposição e o contraste adequados, gasto bastante tempo ajustando os realces para que pareçam “exatamente certos”. Não faço impressão digital, mas imagino que o mesmo princípio se aplique
Infelizmente, frameworks de ferramentas de linha de comando “modernos”, muitas vezes escritos em JavaScript, tendem a ignorar isso
https://www.gnu.org/software/gettext/manual/html_node/The-TE...
Também havia uma configuração para aplicar aos pontos de dados um efeito fraco de “brilho difuso” da mesma cor, fazendo-os parecer pontos luminosos. Faz sentido que, do ponto de vista da saturação das cores — ou seja, da relação sinal-ruído em todo o espectro —, o fundo preto seja melhor
Dá para usar umas 10 cores diferentes quase sem problemas. Além disso, há a vantagem de transmitir informações de ordem/distância, como amarelo entre vermelho e verde, laranja entre vermelho e amarelo, o que facilita segmentar e interpretar o quão próximas duas cores estão
Na verdade, não acho que seja tão difícil assim
Etapa 1: a maioria dos emuladores de terminal tem uma paleta de cores padrão péssima, então basta trocá-la. Pessoalmente, gosto do Solarized, especialmente o tema escuro, mas o tema claro também é bom. Mesmo que não seja Solarized, há muitos temas em que qualquer cor fica legível sobre o fundo padrão
Etapa 2: é preciso evitar ferramentas de linha de comando que usam, por padrão, sequências de escape de cores de 8 bits ou 24 bits. Pode ser controverso, mas, pessoalmente, considero isso hostil ao usuário. Eu já escolhi a melhor paleta de cores de terminal para as minhas necessidades de legibilidade, e não ajuda quando um desenvolvedor se acha uma espécie de falso designer e sobrescreve isso. A ferramenta pode oferecer uma opção para ativar temas, mas deve ser uma opção, não o padrão
Para quem passa a maior parte da vida no terminal, só seguir essas duas regras já permite criar um ambiente de terminal consistente e legível quase sem esforço de configuração. O problema real é que toleramos demais que desenvolvedores usem códigos de escape de cores de 8 bits e 24 bits
Ao longo dos anos, cheguei à conclusão de que novos recursos precisam ser colocados diante dos olhos do usuário, e bons padrões precisam ser empurrados com força. Caso contrário, os recursos quase não são usados
Cores de 8 bits e 24 bits já são recursos opcionais e também configuráveis. Em um programa de terminal que funcione bem, as variáveis de ambiente TERM e COLORTERM determinam se essas cores serão usadas
Muitos aplicativos esperam que texto em “bright black” seja visível sobre o fundo. Há muitos exemplos aqui: https://github.com/altercation/solarized/issues/220
Quase todas as outras paletas de cores representam “bright black” como um cinza legível sobre um fundo preto
Por exemplo, o pamix define o fundo como preto, e a barra de status do tmux ou o ngrok fazem algo parecido. Aí você acaba caindo numa toca de coelho para lidar com isso
As duas coisas sugerem que a solução deve estar no terminal. O programa de terminal, para começar, deve ter cores padrão razoáveis; azul deve ser reconhecivelmente azul e anomalias comuns de percepção de cores também devem ser consideradas. Por exemplo, vermelho puro sobre fundo preto é difícil de ler, então é melhor não usar apenas
ff0000e misturar pelo menos um poucoQuando o terminal passa a ter padrões razoáveis, programas de linha de comando podem usar as 16 cores padrão. Nesse caso, tentar usar cores de 24 bits é quase dizer “desisti de esperar que o lado do terminal forneça normalidade” ou “eu sei melhor do que todo mundo”, e no fim o usuário precisa configurar N programas separadamente. Na minha opinião, o melhor é não definir temas dentro de apps de linha de comando
Vejo sites e fontes de forma parecida. O conteúdo deve ser fornecido em HTML para que o usuário possa vê-lo como quiser, e o layout da página também deve fluir, não ficar fixo como uma diagramação de revista
Em software desktop é parecido. O compositor Wayland deveria lembrar a posição das janelas. Era tolice cada programa X salvar e restaurar a própria posição da janela. O Wayland diz que saber informações do ambiente é um problema de segurança, e eu concordo com isso, mas então essa memória passa a ser responsabilidade do ambiente desktop. Também seria possível remover esse código de todos os apps
A pergunta “em que ponto da pilha de software isso deve ser tratado?” se repete em várias áreas. Ao escolher onde colocar algo, é preciso responder primeiro quais são os objetivos, e minha resposta sempre pende para simplicidade e manutenibilidade
O texto da Julia também menciona essa ideia, mas não entra nos perrengues concretos. Relacionado a isso, também fico curioso se as paletas de cores do terminal lidam apenas com as 16 cores básicas, ou se mexem também nas áreas de RGB e escala de cinza. Afinal, cores de 8 bits e 16 bits também poderiam ser ajustadas para atender a requisitos de legibilidade
Para quem está escolhendo cores, seria bom verificá-las com o novo algoritmo APCA (Advanced Perception of Colour)
O APCA deve substituir, no futuro, o método atual de contraste x:y no WCAG 3.0, mas isso ainda pode levar alguns anos. Dizem que ele considera tamanho da fonte, peso, primeiro plano/fundo, e até a iluminação e o ambiente ao redor, além do uso pretendido
Seria bem interessante se um emulador de terminal pudesse usar o sensor de luminosidade do dispositivo para otimizar o contraste conforme os fatores ambientais
Há completos malucos que querem desligar as cores de vez[0]. Até tenho vontade de tentar, mas também gosto de cores bonitas
[0] https://no-color.org/
:syntax offé minha única configuração do Vim. Porque os conjuntos de cores de terminal foram projetados por programadores de computador, engenheiros eletricistas e pessoas que não sabem que, em cores, o que importa não é a cor em si, mas o brilhoFico curioso se existe alguma correlação entre pessoas que não querem cores no terminal e pessoas que usam bloqueadores de anúncios fortes no navegador ou usam muito o modo leitura
Ao enviar a saída por pipe, a cor vira apenas dívida, sem nenhum benefício. O ponto principal está mais próximo de ter escolha
Fica pior quando se alterna entre Linux e Windows. O uso padrão de cores em muitas ferramentas é quase inutilizável, ou de fato torna a ferramenta inutilizável
Algumas ferramentas oferecem a opção
--color=never, e um bom número respeita NO_COLOR. Infelizmente, nem todas; e mesmo ferramentas que fazem isso às vezes assumem que esse modo será usado apenas em pipelines ou interfaces de programação. Daí surgem todos os tipos de comportamentos infelizesEle tem um conceito consistente de paleta com uma temperatura de cor significativa e pende para o lado quente para cansar menos os olhos que ficam olhando para excesso de tons azulados. Também vem com uma paleta para o alacritty
Há muito tempo eu queria usar um tema claro no terminal, mas sempre desistia porque muitos programas usam cores personalizadas não ANSI otimizadas para fundo escuro de terminal
Alguns programas permitem configurar as cores, mas configurar todos eles um por um parecia trabalhoso demais. Então hoje uso um fundo escuro no terminal, mas escolhi manualmente um tema ANSI em que todas as cores têm uma taxa de contraste suficiente para o meu critério e também passam na verificação de contraste APCA/WCAG 3. Estou satisfeito :)
Com a sequência de controle OSC 11, um programa consegue descobrir a cor de fundo, mas quase nenhum se importa. Em geral, se alguém acha que uma mensagem de aviso amarela parece legal, a história acaba aí
Isso leva a outro problema. Existem terminais populares que não são compatíveis com xterm, mas definem
TERM=xterm256-colorpor padrãoEdição: acabei de descobrir o
xtermcontrol, que permite abstrair a verificação do fundo em scripts e está em todos os principais gerenciadores de pacotesHoje em dia desisti e configuro manualmente a maioria dos apps para usar cores ANSI. Por exemplo, coisas como o fzf têm switches de linha de comando. Deixo apenas Vim e Emacs como apps não ANSI e os configuro para combinar com a paleta usada no restante do terminal. Se quiser, dá para ir um passo além com algo como vim-dim
O Emacs tem um
frame-background-mode[0] pouco descoberto, que na prática élightoudarkQuando você se pergunta por que o Emacs escolheu uma cor estranha para algum item, na maioria das vezes é porque o frame-background-mode está errado
[0]https://doc.endlessparentheses.com/Var/frame-background-mode...
Em um terminal de fundo escuro com texto branco:
export COLORFGBG='15;0'Em um terminal de fundo claro com texto preto:
export COLORFGBG='0;15'Venho usando há quase 10 anos uma paleta FlatUI levemente modificada, e quase nunca tive situações em que ela realmente causasse problemas
arquivo png: https://drive.google.com/file/d/1mkMESeGf7MNdKa-rPDx7Yf9BDit...
link do imgur: https://imgur.com/a/flatui-7mqVZAY
base: https://flatuicolors.com/palette/defo
Eu também uso meu tema há quase 10 anos. Funciona bem no iTerm, vim, Emacs, vscode etc.
Uso o Apple Terminal há muito tempo e, antigamente, havia uma boa coleção de paletas de cores chamada “Terminal Fructose”, então eu costumava usar cores de fundo diferentes para cada tipo de tarefa. A Apple também incorporou isso como temas em algum momento.
Mas a Apple deixou o suporte ao Terminal meio abandonado: ele não suporta mais de 256 cores e também carece de recursos mais modernos. Também não combina muito bem com uma configuração Neovim+LazyVim.
Para encontrar um terminal melhor, fiquei alternando entre iTerm2, Kitty, Alacritty e Wezterm. Todos são mais modernos, mas parecem não ter a opção básica “New Window with Profile ...” para abrir rapidamente janelas com diferentes cores de fundo/temas. Pelo menos não sem alguma gambiarra.
Hoje me fixei no Wezterm, principalmente porque ele também funciona no Windows e permite compartilhar a configuração
wezterm.lua. A propósito, o Windows Terminal também é realmente muito bom. Ainda assim, para tarefas rápidas, como usarpython3como REPL para fazer cálculos ou testar hexadecimal/binário, ainda costumo abrir o Apple Terminal.Há alguns recursos do iTerm2 dos quais sinto falta, mas a maioria é relacionada ao mouse. Fora isso, passei algumas noites configurando do jeito que eu queria e, desde que fiz o
cmd-nabrir uma nova janela no diretório padrão em vez do diretório atual, venho usando satisfeito.launch_menu[1], que inicia outro shell, ou comaugment-command-palette[2], que adiciona itens à paleta de comandos.[1] https://wezfurlong.org/wezterm/config/lua/config/launch_menu...
[2] https://wezfurlong.org/wezterm/config/lua/window-events/augm...
Sim, exige um pouco de gambiarra. Mas programar um recurso bem específico exatamente do jeito que você quer é o auge da experiência WezTerm.
Não só em terminais: em letreiros de neon ou painéis de LED, o azul também é a cor mais cansativa para os olhos à noite.
De longe, ele sempre parece borrado e fora de foco. Quando vejo grandes empresas colocando letreiros gigantes com iluminação azul, acho curioso gastarem tanto dinheiro sem perceber que as pessoas não conseguem ler.
No meu laptop, configurei a alternância automática entre modo claro/escuro conforme o ciclo de luz do dia, e é surpreendente a quantidade de aplicativos com saída colorida que quebram ao mudar para o modo de fundo claro com texto escuro.
Se você está criando uma ferramenta de linha de comando e precisa mesmo usar cores, deveria usar apenas as 16 cores ANSI ou permitir que o usuário final altere a paleta de cores.