16 millones de colores: por qué tu Emacs en terminal se ve peor que `emacs -nw`
El síntoma que no cuadra
Tienes Emacs como daemon (arranca una vez, te
conectas mil). Abres un cliente en la terminal con
emacsclient -t y el fondo del editor se ve distinto:
apagado, transparentándose al fondo del terminal, o directamente un
color raro. Pero si abres emacs -nw —el mismo Emacs, el
mismo theme, la misma terminal— se ve
perfecto: fondo sólido, colores
ricos.
Mismo editor, misma terminal, resultado distinto. Eso no puede ser el theme. Tiene que ser algo del entorno. Y lo es.
Nivel 0: ¿cuántos colores tiene una terminal?
Las terminales no siempre pudieron pintar cualquier color. Han pasado por tres eras, y todas conviven hoy:
| Era | Colores | De dónde salen |
|---|---|---|
| ANSI | 8 / 16 | Los de toda la vida: negro, rojo, verde… |
| 256 | 256 | Una paleta fija (un "cubo" de 6×6×6 + grises) |
| Truecolor | 16.777.216 | 24 bits: cualquier #rrggbb, como en el navegador |
Una app que quiere pintar `#282c34` (el gris azulado de fondo del theme doom-one) necesita que la terminal esté en truecolor. Si la terminal solo ofrece 256, la app tiene que aproximar ese color al más cercano de la paleta fija. Y ahí empiezan los problemas.
Por qué 256 colores te pinta un azul que tú no pediste
El "cubo" de 256 colores no es continuo: cada canal (rojo, verde, azul) solo puede tomar 6 valores: 0, 95, 135, 175, 215, 255. Para pintar un color cualquiera, redondeas cada canal al nivel más cercano.
Coge `#282c34` = (R=40, G=44, B=52):
- R=40 → más cerca de 0 que de 95 → 0
- G=44 → más cerca de 0 → 0
- B=52 → ¡más cerca de 95 (diferencia 43) que de 0 (diferencia 52)! → 95
Resultado: (0, 0, 95) = `#00005f`, un azul marino. El canal azul es el único que redondea hacia arriba, y de un gris oscuro neutro sale un azul cantoso. No es un bug del theme ni de Emacs: es la matemática de encajar un color en una rejilla demasiado gruesa.
En truecolor no hay rejilla: `#282c34` es `#282c34`, exacto, y se ve como debe.
Cómo sabe una app si puede usar truecolor
Aquí está el meollo. Una app (Emacs, vim, lo que sea) decide su número de colores por dos vías:
- La terminfo del `TERM`: una base de datos que describe lo que sabe hacer cada terminal. Si la entrada declara la capacidad de truecolor (`RGB` o `Tc`), la app activa 24 bits. Pero muchas entradas no la declaran aunque la terminal sí lo soporte (le pasa a varias muy populares).
- El plan B: la variable `COLORTERM`. Cuando vale `truecolor` (o `24bit`), la app activa 24 bits aunque la terminfo no lo diga. Las terminales modernas exportan `COLORTERM=truecolor` a los programas que lanzan, precisamente para esto.
O sea: tu terminal te está chivando "puedo con todo" por la variable `COLORTERM`. Si esa variable llega, truecolor. Si no llega, te quedas en 256 y a cuantizar feo.
El daemon: el eslabón que se queda sin la variable
Y ahora se entiende todo. ¿Por qué `emacs -nw` bien y `emacsclient -t` mal?
- `emacs -nw` es un proceso nuevo que lanzas tú desde la terminal. Hereda tu entorno entero, incluido el `COLORTERM=truecolor` que la terminal puso. → 24 bits. Feliz.
- El daemon no lo lanzaste desde la terminal: lo arrancó tu gestor de sesión / de ventanas al iniciar sesión, en un contexto sin `COLORTERM`. Cuando luego te conectas con `emacsclient -t`, el daemon decide los colores con su entorno (el del arranque, pelado), no con el de tu terminal. → 256 colores. Triste.
La diferencia entre que se vea de lujo o regular es una variable de entorno que el daemon no tenía. Nada más.
Detalle fino que cuesta una tarde aprender: Emacs lee `COLORTERM` del entorno real del proceso daemon en el momento de crear cada terminal. Cambiarla "en caliente" desde dentro no basta; tiene que estar puesta cuando arranca el daemon.
El arreglo
Haz que el daemon arranque con la variable. Donde sea que lo lances (el servicio de systemd, el autostart de tu gestor de ventanas, tu script de login), antepón la variable:
COLORTERM=truecolor emacs --daemonReinicia el daemon (esto cierra los clientes abiertos, guarda antes) y listo: los nuevos `emacsclient -t` nacen en 24 bits.
Cómo comprobarlo en 5 segundos
Pregúntale a Emacs cuántas celdas de color cree que tiene su terminal:
M-x eval-expression (display-color-cells)
- `256` → estás en paleta, vas a cuantizar.
- `16777216` → truecolor, a pintar lo que quieras.
Si prefieres verlo con los ojos, este "test del arcoíris" en bash pinta una franja continua: en truecolor es un degradado suave; en 256 colores se ve a bandas.
awk 'BEGIN{
for(i=0;i<256;i++){
r=(i<85)?255-i*3:0; g=(i<85)?i*3:(i<170?255-(i-85)*3:0); b=(i<170)?0:(i-170)*3;
printf "\033[48;2;%d;%d;%dm \033[0m", r, g, b;
} print ""
}'La lección que me llevo (y un guardarraíl)
Cuando algo se ve "casi bien pero raro" en una terminal, antes de tocar el theme mira la profundidad de color. Medio mundo pelea con sus colores sin saber que están atrapados en 256 por una variable ausente.
Y un guardarraíl honesto: si tu config fuerza un color de fondo en terminales, compruébalo solo cuando hay truecolor. En 256 colores, forzar un `#rrggbb` oscuro y desaturado es justo lo que te pinta el azul. Mejor: si el frame es de 24 bits, fuerza el fondo del theme; si no, no lo toques y deja el fondo del terminal. Una línea de defensa que te ahorra el "¿por qué cojones está azul esto?".
— doomguru
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario