- Para ver correctamente temas como Solarized en Emacs dentro de la terminal, lo importante no es tanto el color de 24 bits en sí, sino que la terminal, terminfo, tmux y mosh entiendan la misma capacidad de color de punta a punta
- Los colores RGB se usan ampliamente con la forma
ESC[38;2;<r>;<g>;<b>m, pero la coexistencia de la sintaxis con dos puntos, más cercana al estándar, y la sintaxis con punto y coma difundida en las implementaciones reales complica la compatibilidad xterm-256coloryxterm-directanuncian, respectivamente, una paleta de 256 colores y 16,777,216 colores, pero el modelo de terminfo centrado en paletas no logra representar limpiamente el color RGB directo- En entornos reales pueden hacer falta valores
TERMalternativos como las entradas-directdencurses-term,tmux-direct, la serie mosh 1.4 ovscode-direct, y algunas capas todavía aceptan solo la forma con punto y coma - Para usar de forma estable las capacidades de las terminales modernas,
TERMy terminfo no alcanzan; se necesita una forma de representación separada que actualice más rápido las capacidades por nombre y versión de terminal
Por qué se necesita color de 24 bits en Emacs dentro de la terminal
- Emacs en un entorno gráfico admite automáticamente color de 24 bits, por lo que muestra correctamente temas como Solarized y las fuentes
- Si se usa el mismo tema en una terminal, la representación de color puede estar limitada y la pantalla puede verse peor
- Las terminales populares admiten color de 24 bits desde hace mucho, pero para que un programa lo use deben coincidir tanto la detección de capacidades como la configuración
- El objetivo es doble
- Encontrar cómo activar el soporte de truecolor en el entorno de terminal actual
- Ver cómo el problema de color en Emacs se conecta con los estándares de terminal de las décadas de 1970 a 1990
Códigos de escape ANSI e historia de las extensiones de color
- Las primeras terminales de hardware usaban distintos sistemas de códigos de control, y para crear software portable era necesaria la estandarización ANSI
- Los códigos de escape ANSI existen desde la década de 1970, y en color la pieza clave es SGR (Select Graphics Rendition)
- Negrita o brillo
- Itálica
- Parpadeo
- Color de primer plano y color de fondo
- Otros atributos de visualización de caracteres
- Al principio, el color era de 3 bits, correspondiente a los 8 vértices del cubo RGB
- Incluía negro, blanco, colores primarios aditivos y colores primarios sustractivos
- Más adelante se agregó un bit de color brillante o negrita y se expandió a 16 colores
- “bright black” corresponde a un gris oscuro
- En 1999, Todd Larason agregó a xterm un parche con soporte de 256 colores
- Muestreo de un cubo de color RGB 6x6x6
- Rampa de escala de grises de 24 niveles
- También existe una variante de 88 colores, rara pero todavía soportada
Cómo se creó la sintaxis de color de 24 bits
- En terminales compatibles, el color de 8 bits y el de 24 bits se configuran con las siguientes formas
ESC[38;5;<n>m: establece el color númeronde la paleta como color de primer planoESC[38;2;<r>;<g>;<b>m: establece los valores RGBr,g,bcomo color de primer plano
- Los números
5y2están vinculados con los modos de color extendido de ISO 8613-6, es decir ITU T.4162: color directo en el espacio RGB5: color indexado
- El flujo de estandarización fue el siguiente
- Década de 1970: ANSI estandarizó las secuencias de escape de terminal, lo que derivó en ANSI X3.64 y ECMA-48
- 1979: la segunda edición de ECMA-48 asignó los SGR 30~37 y 40~47 a colores de primer plano y fondo de 3 bits
- 1984: la tercera edición de ECMA-48 introdujo los conceptos de color de primer plano y fondo predeterminados, y les asignó 39 y 49
- 1991: la quinta edición de ECMA-48 dejó 38 y 48 “para estandarización futura” y señaló ISO 8613-6 como pista
- 1993: ISO 8613-6 definió 38 y 48 como modos extendidos de primer plano y fondo
- Para separar subparámetros, usar dos puntos es lo más cercano al estándar, pero las implementaciones reales adoptaron ampliamente el punto y coma
ESC[38;5;3mpuede interpretarse en terminales que no conocen SGR 38 como parámetros separados38,5y3- La FAQ de xterm de Thomas Dickey explica que en aquel momento una copia de ITU T.416 era cara, y que haber separado los valores RGB con punto y coma como si fueran otros parámetros SGR fue un error
- La línea de tiempo relacionada es la siguiente
- 1999: Thomas Dickey fusionó en xterm el parche de 256 colores de Todd Larason, incorporando la sintaxis ambigua con punto y coma
- 2006: Konsole soportó 256 colores y truecolor de 24 bits con la misma sintaxis de punto y coma que xterm
- 2012: xterm se modificó para aceptar también la sintaxis con dos puntos, más cercana al estándar
- 2016: la consola integrada de Windows 10 soportó códigos de escape ANSI y color de 24 bits, pero usó la sintaxis con punto y coma
- 2019: Windows Terminal también soporta códigos de escape ANSI, pero usa la sintaxis con punto y coma
- 2022: Microsoft anunció la transición del ecosistema desde el subsistema de consola estilo VGA heredado hacia la emulación de terminal ANSI
- 2022: Konsole soportó la sintaxis con dos puntos compatible con el estándar
Cómo terminfo representa las capacidades de color
- terminfo proporciona una base de datos de capacidades de terminal y funciones para generar las secuencias de escape adecuadas
- La variable de entorno
TERMapunta al registro terminfo que usará el programa, y también se reenvía automáticamente en conexionesssh toemuestra la lista de registros terminfo instalados, einfocmpse usa para revisar las capacidades de un registro específico- Hay tres capacidades importantes relacionadas con el color
colors: cantidad de colores que soporta la terminalsetaf: configurar color de primer planosetab: configurar color de fondo
- El
setafdexterm-256coloremite secuencias distintas según el número de color- 0~7: usa parámetros SGR ANSI 30~37
- 8~15: usa colores brillantes no estándar 90~97
- Por encima de eso: usa la paleta de 256 colores en la forma
38;5;<n>
xterm-directes una entrada terminfo para RGB de 24 bits que anunciacolorscomo 16,777,216- Desactiva
ccc, indicando que no se pueden asignar nuevos valores RGB a índices de color - También omite entradas relacionadas con cambios de color en tiempo de ejecución, como
initc,ocyrs1 setafysetabusan la forma basada en dos puntos38:2::...
- Desactiva
Límites del modelo de color directo de terminfo
- El modelo de programación de terminfo y ncurses está básicamente centrado en entradas de paleta
- Hay N entradas de paleta
- Cada entrada tiene un valor RGB predeterminado
- Se asume un modelo en el que la terminal puede cambiar esos valores
- Las terminales
-directrepresentan el color de 24 bits como si hubiera 16,777,216 entradas de paleta- Cada entrada corresponde al cubo RGB 8:8:8
- Los valores no se pueden cambiar
- Por compatibilidad, el enfoque de
xterm-directusa los 7 azules más oscuros para compatibilidad con los 8 colores ANSI básicos- Se excluye el negro
- Es un mecanismo para evitar que programas existentes, al asumir el significado de
setaf, impriman un azul oscuro casi invisible
- Por eso, el enfoque
-directy el enfoque-256colorno son compatibles entre sí- El programa debe saber que 256 colores son colores indexados y que 16,777,216 colores son color directo
- También existe la excepción de tener que evitar los 7 azules más oscuros
- En un problema relacionado con termwiz, el programa esperaba la paleta de xterm-256color, pero en la práctica imprimía tonos de azul oscuro difíciles de leer
- Ese issue estaba abierto al momento de escribir, pero @quark-zju incorporó una corrección y actualmente termwiz se comporta de forma razonable
- El punto central está más en las restricciones de terminfo que en la terminal en sí
- Las terminales que soportan color de 24 bits parecen soportar también la paleta de 256 colores de xterm y cambios dinámicos de valores RGB
- terminfo no alcanza para representar con precisión y rapidez el ecosistema moderno de emuladores de terminal
Configuración de TERM y compatibilidad con punto y coma
- Como muchos programas usan terminfo, el valor de
TERMdebe configurarse correctamente - Aunque se quisiera unificar todo con la sintaxis SGR basada en dos puntos, varios entornos todavía soportan solo la sintaxis con punto y coma
- Las entradas terminfo se componen de bloques de construcción
xterm+direct: sintaxis con dos puntos, más cercana al estándarxterm+indirect: para terminales heredadas que solo soportan punto y coma
- Al buscar
xterm+indirect,vscode-directpareció ser la opción más adecuada- Como apunta a terminales de Microsoft, se consideró lo suficientemente cercana a Windows Terminal y Windows Console
- No se auditaron todas las capacidades, pero funciona
- Muchos servidores podrían no tener instaladas las entradas terminfo
-direct- En la mayoría de los sistemas, la base de datos terminfo básica está en el paquete
ncurses-base - Las entradas de terminal extendidas requieren el paquete
ncurses-term
- En la mayoría de los sistemas, la base de datos terminfo básica está en el paquete
- Mientras se escribía esto, ncurses agregó una entrada terminfo
winconsole, pero no soporta color de 24 bits y todavía no fue publicada en ninguna versión de ncurses
Cómo Emacs detecta truecolor
- Emacs documenta cómo detecta el soporte de truecolor en TTY
- Si se ejecuta
(display-color-cells)enM-x eval-expression, se puede confirmar si Emacs reconoce 16,777,216 colores - La documentación de Emacs también cubre las limitaciones de terminfo en modo
-direct- Las terminales con la capacidad
RGBpueden tratar#000001a#000007como colores indexados, no como RGB directo - Esto se hace para mantener la compatibilidad hacia atrás con aplicaciones que no conocen direct color
- Si causa problemas, se puede usar una definición de terminal personalizada con
setb24ysetf24
- Las terminales con la capacidad
- Emacs busca primero las cadenas
setf24ysetb24; si no existen, usaRGBcomo capacidad alternativa - Las entradas terminfo revisadas en el sistema no incluían
setf24
En terminales anidadas, todas las capas deben coincidir
- Un flujo de trabajo común anida varias capas de terminal
- Abrir un emulador de terminal gráfico en el escritorio local
- Conectarse por mosh a una máquina remota o VM
- Iniciar tmux
- Usar además una terminal interna de Emacs, Asciinema, GNU Screen, etc.
- Cada capa implementa por su cuenta una máquina de estados de secuencias de escape ANSI
- Para que el color de 24 bits funcione, todas las capas deben entender las secuencias de escape generadas por terminfo según el valor
TERMinterno y reenviarlas correctamente de acuerdo con el terminfo externo - Por lo tanto, el software relacionado debe estar lo suficientemente actualizado
- El Ubuntu LTS actual ofrece mosh 1.3, así que hubo que habilitar el PPA mosh-dev
- El
TERMdentro de cada capa también debe ser correcto- Dentro de tmux se usa
tmux-direct - Como mosh no tiene un terminfo estándar, hay que elegir un valor suficientemente cercano
- Dentro de tmux se usa
Configuración por entorno
-
Emulador de terminal gráfico
- La mayoría de las terminales configuran un
TERMpredeterminado adecuado o permiten que el usuario lo sobrescriba - Konsole tiene una opción para elegir el valor de
TERM
- La mayoría de las terminales configuran un
-
ssh
sshreenvía el valor deTERMa la nueva shell- Si el host remoto tiene el mismo registro terminfo, la configuración es relativamente simple
-
tmux
- Al ejecutar tmux,
TERMpuede quedar configurado comoscreen - Se resuelve cambiando la terminal predeterminada en
~/.tmux.conf
set -g default-terminal "tmux-direct"- También se puede considerar una configuración condicional que use
tmux-directsolo cuando elTERMexterno soporte color de 24 bits, y que de lo contrario mantengascreenotmux-256color
- Al ejecutar tmux,
-
mosh
- Las versiones recientes de mosh soportan color de 24 bits, pero por sí mismas solo anuncian 8 o 256 colores
- Por lo tanto, el usuario debe configurar
TERMadecuadamente - mosh apunta a compatibilidad con xterm, pero en SGR 38 y 48 solo soporta la sintaxis con punto y coma
TERM=xterm-directno funciona- Se usó
vscode-directcomo la alternativa más cercana axterm-direct - Como no hay una variable cómoda que indique si mosh se está ejecutando, se escribió el script
detect-mosh.rspara llamarlo desde.bashrc - El método consiste en verificar si el proceso de la shell es hijo de
mosh-server - No se determinó si compilar Rust durante la ruta de login es adecuado para hosts de bajo rendimiento
Resultado final y problemas restantes
- Después de la configuración, el tema también se muestra con color de 24 bits en Emacs dentro de tmux y mosh
- Los problemas restantes se resumen en tres puntos
- Las terminales no acuerdan completamente la sintaxis ni las capacidades
- terminfo es el camino estándar para consultar capacidades
- terminfo es limitado y a veces inexacto, y sus nuevas versiones tampoco salen con frecuencia
Hacia dónde ir después de terminfo
- El software que quiera aprovechar suficientemente las capacidades modernas de terminal necesita alejarse de terminfo
- Las posibles direcciones son las siguientes
- Seguir usando la variable
TERM, que está ampliamente soportada - No depender solo del terminfo antiguo del sistema operativo o la distribución, y permitir que los programas conozcan las capacidades de la terminal de forma independiente
- Incluir en una biblioteca actualizada con frecuencia información de emuladores de terminal de los últimos 10 años aproximadamente, por nombre y versión
- No incluir soporte para terminales de hardware que ya son difíciles de usar
- Seguir soportando los archivos terminfo provistos por el OS y el formato de archivos terminfo, pero contar con un protocolo para determinar qué información es la más reciente
- Distinguir diferencias de capacidades por versión, como Konsole 2022 y Konsole 2023, mediante un
TERMVERSIONopcional - Representar sin ambigüedad capacidades modernas como color de 24 bits, animación de paletas de 256 colores, enlaces URL y el protocolo gráfico de Kitty
- Seguir usando la variable
- También es posible un método retrocompatible para programas heredados
- Un programa ejecutado desde
.bashrcusaTERMyTERMVERSIONpara generar un archivo terminfo binario en$HOME/.terminfo/ - Genera capacidades claras de color de 24 bits como
RGB,setf24ysetb24 - Considera que los programas que no conocen RGB asumen una paleta de 256 colores, y mantiene
colors#0x100,initcyoc
- Un programa ejecutado desde
1 comentarios
Comentarios de Hacker News
Hurgar en terminfo se siente como iluminar jeroglíficos con una antorcha parpadeante en unas catacumbas profundas.
Es raro si uno piensa cuánta complejidad hay dentro de una sola app de terminal, y hace que agradezca más a los desarrolladores de terminales como iTerm y Kitty.
Reuní algunas funciones para configurar el color de las pestañas en iTerm+zsh: https://gist.github.com/aclarknexient/84ebe33c1879f921685304...
Comparado con la forma de antes de conectarse a HTTP o SMTP vía telnet, el texto en sí puede ser simple, pero lo que muestra ese texto es una aplicación compleja que soporta todo tipo de funciones.
Ahora es una decisión posible porque prácticamente soy el único usuario de esa terminal, pero las terminales modernas soportan bastante bien un subconjunto común, así que es menos doloroso que tener apps confundidas porque no reconocen un valor
TERMdesconocido.Claro, si no entras por SSH a sistemas nuevos con frecuencia, es un problema menos importante.
No es el emulador de terminal más rápido, pero visualmente es por lejos el mejor.
Me resultó más fácil ajustar la paleta de 16 colores en varias apps de terminal que hacer coincidir exactamente el código de terminal del lado de la aplicación.
Configuré los colores de rxvt-unicode en
~/.Xdefaults, y en el tema.elde Emacs asigné nombres de colores distintos según si la visualización era gráfica, para luego aplicarlos a varias faces.Como extra, la salida de
lscon colores también se ve mejor. La paleta básica de 16 colores muchas veces tiene demasiada saturación y mal contraste.(if (display-graphic-p)es la clave.Emacs soporta una salida gráfica real, y en X11/Cocoa/Win32 Esc funciona como un Esc real; también permite bindings con Ctrl+Shift o Cmd, usar varias fuentes al mismo tiempo, mostrar imágenes, cambiar la forma del cursor, etc.
Es como una máquina del tiempo que te lleva 20 años al futuro, a 1989.
Una línea roja era rojo intenso o apagada, y si se sumaba la línea de intensidad, quedaba rojo al 100%.
DIRCOLORS,lstambién soporta realmente color de 24 bits.Los colores básicos son demasiado oscuros contra un fondo oscuro, así que subí la luminancia de todos los colores.
Si el autor hubiera conocido
export COLORTERM=truecolor, creo que habría sufrido mucho menos.También aparece en la nota al pie sobre detección de truecolor de la documentación de Emacs enlazada y se ve en la captura de Konsole, pero es posible que se haya perdido dentro de varias capas de multiplexores de terminal.
Al configurar este valor, la app entiende de inmediato que se quiere truecolor, así que se puede saltar la parte difícil y ni siquiera hace falta la base de datos terminfo.
RGBde terminfo.Dicho eso, no todos los programas respetan COLORTERM, así que en algún momento tenía en
.bashrcque, cuando eralinux | screen*, hiciera unset deCOLORTERM, y en los demás casos exportaraCOLORTERM=truecolor.Hoy Screen soporta color de 24 bits, así que probablemente era una configuración de la época de Ubuntu 18.
tramposshfs.Por otro lado, también se debe a que el mantenedor de ncurses es bastante conservador y los desarrolladores de terminales nuevas quieren moverse rápido.
En versiones más antiguas de Emacs todavía se necesita la base de datos terminfo.
La mayoría de las veces no hace falta definirlo, pero si en una sesión de screen está configurado
COLORTERM=truecolor, de pronto la pantalla se ve muy extraña, y al borrar la variable de entorno vuelve a verse normal.No es estrictamente necesario usar la terminal para interactuar con Emacs
Se puede usar un frontend gráfico para MacOS, Windows, X.org y Wayland
Si se desactiva la barra de herramientas, el Emacs gráfico se parece tanto al Emacs que corre en la terminal que alguien que no conoce Emacs podría confundir fácilmente la ventana gráfica de Emacs en la computadora de un colega con una ventana de terminal
En una encuesta a usuarios de Emacs, el 80% respondió que usa un frontend gráfico
xterm-mouse-modese obtiene el 80% de los beneficiosCon
mouse,xterm-mouse-mode,mouse-wheel-mode, configuración de scroll, etc., queda bastante usable, yauto-save-defaultse deja ennil, como Dios mandaTodos los programas de terminal se ejecutan en un búfer shell-mode del Emacs gráfico, y solo uso term-mode para los pocos programas que necesitan control de pantalla completa
No es lo más completo ni lo más rápido, pero se puede navegar como cualquier otro búfer e integrarlo sin fricción con lo que se está editando
Si no puedo abrir un Emacs gráfico en una máquina remota, edito archivos remotos con tramp, o levanto un servidor Emacs headless y me conecto con un emacsclient gráfico
Nunca había considerado que la gente pudiera pensar que ejecuto Emacs en la terminal
El Emacs gráfico es mucho mejor, pero sigue siendo excelente que en la terminal funcione y se vea igual en aproximadamente un 90%
La sensación es tan liviana como la terminal, no como VNC
Tiene ventajas como fuentes, uso simultáneo de distintas fuentes, menús, mouse, colores y varios frames/ventanas
Si se ejecuta la parte gráfica localmente y se accede a sistemas remotos con tramp, en la práctica se pueden editar incluso archivos de configuración de un router remoto basado en Linux con prácticamente solo busybox, con todo tipo de comodidades
Uso X11 de forma intermitente desde los 90, pero con las fuentes sigo al nivel de buscar hasta encontrar por casualidad un comando que funciona y luego no tocarlo más
El rendimiento de renderizado de la mayoría de los programas de terminal sigue siendo visiblemente más rápido que las configuraciones de X11 que uno suele tener que usar en entornos corporativos
Hoy en día basta con instalar un Emacs reciente, abrir una terminal compatible con xterm de 24 bits y ejecutar
emacs -nwSi después de aplicar el tema se ve bien, listo; si no, agregá
export COLORTERM=truecolora.bashrc,.zshrc,.fishrc, etc., y luego recargá el shell o ejecutá solo esa línea y reiniciáemacs -nwEste artículo hace parecer que hay que meterse con terminfo, pero normalmente no hace falta. Tal vez hace 10 años, pero ya no
Lo volví a comprobar rápido en iTerm en MacOS y en Alacritty, Kitty y Gnome Terminal en Linux; hoy el soporte para xterm de 24 bits es común
Hoy me enteré de que las secuencias de escape ANSI estándar también funcionan en el símbolo del sistema de Windows 10
El color de 24 bits también funciona bien
Si ejecutás
echo ^[[48;2;255;0;0mHello^[[0m, Hello se imprime con fondo rojoRGB(255,0,0), y^[[0mrestaura el color^[debe ingresarse conCTRL-[; no hay que tipear^y[por separado\x1bo el alias\ejunto con un comando que acepte códigos de escapePor ejemplo, se puede hacer
echo -e '\e[48;2;255;0;0mHello\e[0m'Sin embargo, en scripts
echo -eno es estándar y elechonormal también difiere en casos límite, así que conviene usar siempreprintf '\e[48;2;255;0;0mHello\e[0m\n'DEVICE=C:\DOS\ANSI.SYSal archivoC:\CONFIG.SYSComparado con vim/neovim, lo mejor de Emacs es que no es simplemente un emulador de terminal dentro de una ventana, sino que tiene soporte GUI de primera clase
Sé que existen gVim y un montón de frontends mediocres para neovim, pero el modo de ejecución predeterminado de Emacs es una GUI real, y eso me gusta
La terminal también está bien, pero tiene demasiados residuos históricos y limitaciones, y muchas cosas que ya no tienen sentido en esta época
Si el problema es ejecutar Emacs en un servidor remoto, existen TRAMP y emacsclient
Es frustrante cuando una app GUI no permite copiar el texto que muestra y hay que volver a escribirlo a mano
https://github.com/neovim/neovim/wiki/Related-projects#gui
Me gustan mucho la edición modal y vim, pero me resultaba difícil soportar las soluciones a medias que ofrece un editor de terminal
Si existe una plataforma gráfica rica, ¿por qué no usarla?
Por ejemplo, uso vim casi solo para editar archivos, y para herramientas externas como
git, linters, formateadores, depuradores y manipulación del árbol de archivos vuelvo al shellPor eso mi aplicación principal ya es el emulador de terminal, y en este flujo de trabajo la falta de una GUI dedicada casi no importa
En realidad, me gustaría que mi Emacs se viera así: https://imgur.com/a/h0jA1ro
No lo digo en serio, es broma. Solo uso Cool Retro Term cuando doy presentaciones
Viendo bien, en mi Emacs los colores de 24 bits funcionan por defecto: https://imgur.com/a/BM5OTxp
Aunque el resaltado de sintaxis me molesta un poco
Cool Retro Term es excelente, y también me gustaría probarlo en alguna presentación
Personalmente, los demás terminales retro no se ven tan bien como este
Es realmente vergonzoso que hayan encerrado el estándar detrás de un precio tan alto
La gente tiene que dar tantos rodeos para no comprarlo, y hasta pueden darse resultados como este
Si es un estándar, debería ser accesible. En la época en que solo salía en libros, quizá tenía sentido cobrar por la impresión, pero cuesta creer que un PDF mediocre costara 200 dólares
Escribí el parche de color de 24 bits para xterm, pero recién hoy me enteré de cómo hacer funcionar ncurses con
xterm-directYa estaba usando mi propia biblioteca de terminal hecha en Lisp, pero sigue siendo útil tener una ruta alternativa con ncurses
Gracias a Mr. Dickey por responder la pregunta en Stack Overflow y a Chad por sacar el tema