Detectar la cantidad de Unicode que admite mi terminal, incluso a través de la pantalla

10

Aquí está el problema: quiero poder discernir si mi terminal es capaz de unicode decente o no, para usar algunos caracteres o no, al igual que las miradas, que a veces usan colores y otros subrayan.

La motivación surge porque en cualquier tipo de terminal virtual obtengo fuentes decentes, pero entiendo que la consola básica de Linux tiene un conjunto de caracteres de 256 o 512 símbolos simultáneos, por lo que no puede esperar un soporte completo de fuentes.

Al principio pensé que podría usar $TERMo tty, pero aquí está el truco: también estoy usando byobu, por $TERMlo que siempre es "screen.linux". El resultado de tty tampoco es muy revelador: /dev/pts/<some number>tanto en términos "reales" como virtuales.

$BYOBU_TTYtampoco es una ayuda, porque, por ejemplo, puede serlo /dev/tty1y cuando la sesión se abre en Ctrl+ Alt+ F1los caracteres no se muestran, pero cuando se adjuntan a la misma sesión desde un término X, se muestran correctamente y aún $BYOBU_TTYno cambian. Además, me gustaría poder detectar esto sin suponer que byobu está allí o no.

Además, la configuración regional se muestra en todos los casos en_US.UTF-8

Sin embargo, de alguna manera echa un vistazo (para nombrar una herramienta particular que veo detectar esto), incluso dentro de byobu, usa diferentes resultados dependiendo del terminal que estoy conectando a la sesión de byobu.

Tengo problemas con google porque terminal y tty parecen términos de búsqueda demasiado comunes. A lo sumo llego a soluciones recomendadas $TERMo tty.

Álex
fuente

Respuestas:

6

Bueno, primero supongo que señalaría que casi todos los terminales en estos días son "virtuales" en el sentido en que hablas ... incluso si el terminal está en el otro extremo de un puerto serie de buena fe. Quiero decir, ¡los días de VT-100 s, terminales Wyse y otras terminales "físicas", "reales" se han ido prácticamente!

Aparte de eso, supongamos que desea detectar qué tipo de soporte Unicode tiene su terminal. Puede hacerlo escribiendo caracteres de prueba en is y viendo lo que sucede. (Puede hacer un esfuerzo para borrar los caracteres de prueba después de haberlos escrito, pero el usuario aún puede verlos brevemente, o borrarlos podría no funcionar correctamente en primer lugar).

La idea es pedirle al terminal que le diga la posición del cursor, generar un carácter de prueba, pedirle nuevamente al terminal que le diga su posición y comparar las dos posiciones para ver qué tan lejos se movió el cursor del terminal.

Para preguntarle a la terminal su posición, vea aquí . Esencialmente:

echo -e "\033[6n"; read -d R foo; echo -en "\nCurrent position: "; echo $foo | cut -d \[ -f 2

Intenta generar "é". Este carácter toma 2 bytes en UTF-8 pero se muestra en una sola columna en la pantalla. Si detecta que la salida "é" hace que el cursor se mueva 2 posiciones, entonces el terminal no tiene soporte UTF-8 y probablemente haya generado algún tipo de basura. Si el cursor no se movió en absoluto, entonces el terminal probablemente sea solo ASCII. Si se movió 1 posición, entonces felicitaciones, probablemente puede mostrar palabras en francés.

Intenta generar "あ". Este carácter ocupa 3 bytes en UTF-8 pero se muestra en solo dos columnas en la pantalla. Si el cursor se mueve por 0 o 3, malas noticias, similar a la anterior. Si se mueve en 1, entonces parece que el terminal es compatible con UTF-8 pero no conoce los caracteres anchos (en fuentes de ancho fijo). Si se mueve por 2 columnas, todo está bien.

Estoy seguro de que hay otros caracteres de sonda que podría emitir que conducirían a información útil. No conozco una herramienta que haga esto automáticamente.

Celada
fuente
1
Gracias por la sugerencia, Celada. Sin embargo, no funciona: veo correctamente que se informaron las posiciones avanzadas (1 para é, 2 para あ). La única diferencia es que dentro de XI veo los personajes reales, mientras que en tty1 veo un diamante. Entonces, supongo que el terminal realmente admite utf-8, pero carece del carácter en la fuente que se está utilizando.
Álex
Ahora he visto el comando showconsolefont. Esto parecía una posible solución (con -v informa que la fuente es de 512 caracteres). Lamentablemente, solo funciona cuando no se usa byobu. En este último caso, se equivoca con "No se pudo obtener un descriptor de archivo que se refiera a la consola". Si paso explícitamente el tty (opción -C), el error se convierte en "No se pudo abrir / dev / pts / 37"
Álex
Por cierto: sh script para determinar el ancho del terminal de una cadena (pero de eso no se trata esta pregunta)
Gilles 'SO- deja de ser malvado'
3

La pregunta real de OP es: ¿qué valores Unicode admite la consola Linux? ¿Se pueden detectar estos durante la ejecución screen? En principio, uno puede hacer esto recuperando el mapa Unicode para la consola.

El kbdárbol fuente contiene getunimap(y su página de manual). La página del manual dice que

El programa getunimap es antiguo y obsoleto. Ahora es parte de setfont

lo cual no es exactamente cierto. setfonttiene una opción que hace aproximadamente lo mismo:

   -ou file                                  
          Save previous Unicode map in file

Las diferencias:

  • setfontescribe en un archivo, mientras getunimapescribe en la salida estándar
  • getunimap muestra el carácter que se mapearía, como un comentario.

Por ejemplo:

0x0c4   U+2500  # ─ 
0x0c4   U+2501  # ━ 
0x0b3   U+2502  # │ 
0x0b3   U+2503  # ┃ 
0x0da   U+250c  # ┌ 
0x0da   U+250d  # ┍ 
0x0da   U+250e  # ┎ 
0x0da   U+250f  # ┏ 
0x0bf   U+2510  # ┐ 
0x0bf   U+2511  # ┑ 
0x0bf   U+2512  # ┒ 
0x0bf   U+2513  # ┓ 
0x0c0   U+2514  # └ 
0x0c0   U+2515  # ┕ 
0x0c0   U+2516  # ┖ 
0x0c0   U+2517  # ┗ 

versus

0xc4    U+2500
0xc4    U+2501
0xb3    U+2502
0xb3    U+2503
0xda    U+250c
0xda    U+250d
0xda    U+250e
0xda    U+250f
0xbf    U+2510
0xbf    U+2511
0xbf    U+2512
0xbf    U+2513
0xc0    U+2514
0xc0    U+2515
0xc0    U+2516
0xc0    U+2517

Si está ejecutando screen(o, por ejemplo, ejecutando xtermy no en la consola), obtendrá un error de permisos que puede solucionar usando sudo.

Si sé qué fuente se cargó, puedo verificar eso (sin permisos especiales) usando psfgettable, por ejemplo,

zcat /usr/share/consolefonts/Lat2-Fixed16.psf.gz | psfgettable -

y vea los datos de mapeo que setfontusaría para cargar la fuente (con el mapeo Unicode):

#
# Character table extracted from font -
#
0x000   U+00a9
0x001   U+00ae
0x002   U+00dd
0x003   U+0104
0x004   U+2666 U+25c8 U+fffd
0x005   U+0105
0x006   U+0111
0x007   U+0150
0x008   U+0151
0x009   U+0162
0x00a   U+0164
0x00b   U+0170
0x00c   U+0171
0x00d   U+021a 
0x00e   U+02dd  
0x00f   U+2014 U+2015
0x010   U+2020
0x011   U+2021
0x012   U+2022 U+25cf
...

Ambos getunimapy setfontdan los datos sin clasificar, mientras que psfgettableparecen estar ordenados (además de combinar líneas para valores Unicode que se asignan al mismo glifo). Entonces hay diferencias, pero la información es accesible.

Lectura adicional (que ilustra por qué no puede usar showconsolefontpara resolver este problema):

Thomas Dickey
fuente
Gracias, Thomas, por aclarar mi pregunta original y ponerme en el camino correcto. Trataré de obtener una línea simple de su información y volver con los resultados. Usar sudono es un obstáculo para mi caso de uso.
Álex
Ahora, esto es curioso: setfontno genera nada (no crea el archivo dado ni genera un error) dentro de terminales virtuales, pero funciona en terminales reales como se esperaba. Esto está en Ubuntu 16.04
Álex
2

Me encontré con esta pregunta cuando intentaba lograr lo mismo, pero no quería dejar nada en la pantalla y configurar una variable, así que puse lo siguiente en un script de shell que obtuve:

function test_unicode {
  echo -ne "\xe2\x88\xb4\033[6n\033[1K\r"
  read -d R foo
  echo -ne "\033[1K\r"
  echo -e "${foo}" | cut -d \[ -f 2 | cut -d";" -f 2 | (
    read UNICODE
    [ $UNICODE -eq 2 ] && return 0
    [ $UNICODE -ne 2 ] && return 1
  )
}

test_unicode
RC=$?
export UNICODE_SUPPORT=`[ $RC -eq 0 ] && echo "Y" || echo "N"`
unset test_unicode
Jeff
fuente
1
Gracias por la contribución, Jeff. Lamentablemente siempre obtengo Y, incluso en la consola básica: S
Álex