
Cuando ejecuta cal en Linux, la salida del mes actual resaltará el video inverso del día actual. Cuando envío esa salida a hexdump -c, obtengo algunos resultados interesantes:
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 puede ver, se está imprimiendo una secuencia invisible de _\b _\b antes del '3' que está resaltado para hoy. _ siendo guión bajo (5F en ASCII hexadecimal) y \b siendo Ctrl-H o 08 en ASCII hexadecimal. ¿Qué es esto? Sé que hay muchos códigos de terminal oscuros, pero esperaría que usara algo más estándar como \e[7m. Lo que es aún más extraño es que no puedo reproducir el mismo comportamiento de cal imprimiendo los mismos caracteres usando funciones printf estándar como uno de estos comandos:
/usr/bin/printf "1 2 _\b _\b3 4 5\n"
/usr/bin/printf "1 2 _^H _^H3 4 5\n"
Donde ^H se crea presionando Ctrl-V Ctrl-H. Pero ninguno de estos produce la misma salida de video inversa que produce cal. Incluso intenté escribir un pequeño programa en C para hacerlo también. También lo intenté con echo -e. Lo interesante es que si bien no invierte el video en la terminal, si canalizo la salida desde less -R, cambia su color a amarillo y lo subraya. En otros terminales lo probé solo lo subraya. Casi parece exagerado, pero si uso un carácter distinto de _ no funciona, lo que me hace pensar que _\b es una secuencia de código única. ¿Y cómo se invierte el vídeo de ese personaje?
¿Alguna idea de esto?
La página de manual dice que se supone que la salida de cal es una versión compatible bit por bit con el comando cal original de Unix. Así que sólo puedo asumir que se trata de algún código antiguo.
Respuesta1
Casi parece demasiado llamativo.
Eso es exactamente lo que es. Como se discutió en¿Por qué hay 11 tabulaciones en una consola de 80 columnas?, ayuda pensar en la acción de las máquinas de escribir mecánicas cuando se trata de terminales Unix. En este caso, la secuencia _
BS (el carácter de retroceso) antes de un carácter es una convención que se utiliza para indicar el subrayado de ese carácter, porque en algunos terminales así es como se subraya el texto. Una secuencia de control alternativa es BS _
después del personaje. En los terminales originales no importaba qué sobrepasaba a qué, por supuesto. En los terminales de vídeo contemporáneos, el último carácter que se escribe “gana”, borrando los datos anteriores. Por lo tanto, la _
BS <personaje>Se prefiere el orden.
FreeBSD ncal
, que es lo que es este programa, tiene dos modos de funcionamiento a la hora de resaltar.
- Si su salida es una terminal, busca las secuencias
so
yse
para el tipo de terminal actual en la base de datos termcap y las emite a ambos lados del texto resaltado. (En realidad, hay un error en el código que hace esto, que tiene que ver con un buffer en la pila que queda fuera de alcance y su contenido se usa más tarde, que nadie parece haber detectado). - Si su salida no es un terminal, emite el texto con cada carácter a resaltar precedido por una
_
secuencia BS.
No puede replicar esto emitiendo una _
secuencia BS a su terminal, a menos (por supuesto) que su terminal sea uno de los terminales donde así es como se subrayan las cosas. Este no es el caso de los emuladores de terminal, y casi con seguridad no es el caso de cualquier terminal o emulador de terminal que esté utilizando aquí.
Puedes, sin embargo,filtrartexto que usa esta convención, a través del ul
programa, que reconoce esta y varias otras convenciones similares a las de las máquinas de escribir y las traduce a cualesquiera que sean las secuencias de control para la terminal, buscándolas en la base de datos termcap. También puede filtrar las salidas de sus printf
comandos a través de ul
.
En otros terminales lo probé solo lo subraya.
Irónicamente, filtrar la salida en modo no terminal a ncal
través del ul
programa es de hecho ligeramente superior a permitir ncal
escribir las secuencias de control del terminal. Mientras que ncal
utiliza el terminaldestacarmodo, ul
intentará utilizar la configuración real del terminal.subrayarmodo (si lo tiene) al traducir la _
secuencia BS. Como explica el manual de termcap, el modo destacado puede ser cualquiera que sea adecuado para el terminal (incluyendo negrita, video inverso o colores) y no necesariamente está subrayado. En uno de tus terminales se ve claramente una combinación de subrayado y cambio de color.
Además, ul
también funciona con terminales que no tienen secuencias de inicio/fin de subrayado, pero que sí tienen secuencias de último carácter subrayado. Irónicamente, ul
se las arreglará si su terminalrealmente esuno que destaca por tener BS _
después de cada personaje, mientras que ncal
no da abasto.
Y, por supuesto, ul
no tiene ncal
el error de manejo del búfer. ☺
Si canalizo la salida a
less -R
, cambia su color a amarillo y la subraya.
Como habrás notado, el less
programa entiende _
las secuencias BS y las maneja de manera similar a como ul
lo hace el programa. No es completamente lo mismo. ul
puede manejar secuencias que involucran múltiples _
caracteres y BS, y también puede manejar secuencias similares en negrita. less
no puedo. Compara lo que ves en estos dos:
/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
en los buenos viejos tiempos
Lamentablemente, estos todavía son "los buenos viejos tiempos". No dejes que la gente te engañe haciéndote creer que esto rara vez se usa hoy en día.
No está en el manual, pero el código fuente ul
señala que está intentando implementar el procesamiento de secuencia de control de un Teletipo Modelo 37 porque "eso es lo que nroff
genera". El sustituto GNU del nroff
programa Unix original, escrito mucho después de que los terminales adquirieran características sofisticadas como colores, negrita y cursiva, es capaz de generarECMA-48secuencias de control para colores, negrita y cursiva. En realidad lo haceen el caso normal.
nroff
, y su reemplazo GNU, se utilizan para formatear páginas de manual para mostrarlas en su terminal. Lamentablemente, e irónicamente, aproximadamente 10 años después de que se escribiera, la gente procedió a obstaculizar la herramienta GNU para que generara las antiguas secuencias del Teletipo Modelo 37 de 1968 en lugar de las "nuevas" secuencias de control ECMA-48 de 1976 (¡sic!). Hicieron man
invoke groff
con opciones que modificaron su comportamiento predeterminado y agregaron archivos indocumentados que forzaron una salida ditroff adicional.
Cada vez que lee una página del manual en su terminal, se ejecuta el sistema del manual groff
, que convierte diligentemente el texto fuente del manual en un flujo de caracteres de salida con estas antiguas secuencias de control Teletype Model 37, que se less
están more
convirtiendo en las secuencias de control de su terminal.
Otras lecturas
- Jonathan de Boyne Pollard (2016). Cursiva y color en páginas de manual en una terminal virtual de espacio de usuario (versión archivada,versión actual). El paquete de comida.
- Jonathan de Boyne Pollard (2017).
Una página de manual mejorada para
ul
(versión archivada,versión actual). Propuestas.
Respuesta2
Ctrl-H
es retroceso, mueve el cursor un paso hacia la izquierda. Enviar un guión bajo, un retroceso y algún otro carácter era la forma de subrayar algo en una terminal impresa ("papel") en los viejos tiempos. Esto se usó para resaltar el día actual en la salida de cal
.
Mi cal
programa, cuando se ejecuta, konsole
no genera esta secuencia. Si ejecuto script -c cal
y examino el typescript
archivo resultante, puedo ver que el programa cal usa la secuencia de escape <esc>[7m
para cambiar al video en modo inverso.