Détectez la quantité d'Unicode prise en charge par mon terminal, même via l'écran

10

Voici le problème: je veux pouvoir discerner si mon terminal est capable d'unicode décent ou non, afin d'utiliser certains caractères ou non, tout comme les regards, qui utilise parfois des couleurs et d'autres soulignent.

La motivation vient du fait que dans tout type de terminal virtuel, je reçois des polices décentes, mais je comprends que la console Linux de base a un jeu de caractères de 256 ou 512 symboles simultanés, vous ne pouvez donc pas vous attendre à une prise en charge complète des polices.

Au début, je pensais que je pouvais utiliser $TERMou tty, mais voici le hic: j'utilise aussi byobu, $TERMtout comme "screen.linux". La sortie de tty n'est pas non plus très révélatrice: /dev/pts/<some number>en termes "réels" et virtuels.

$BYOBU_TTYn'est pas une aide non plus, car par exemple cela peut être /dev/tty1et lorsque la session est ouverte en Ctrl+ Alt+ F1les caractères ne s'affichent pas mais lors de l'attachement à la même session à partir d'un terme X, ils s'affichent correctement et $BYOBU_TTYne changent toujours pas. De plus, j'aimerais pouvoir détecter cela sans présumer que byobu est là ou non.

De plus, les paramètres régionaux s'affichent dans tous les cas en_US.UTF-8

Pourtant, les regards (pour nommer un outil particulier que je vois détecter), même à l'intérieur de byobu, utilisent des sorties différentes en fonction du terminal que j'attache à la session byobu.

J'ai des problèmes avec Google, car terminal et tty semblent des termes de recherche trop courants. Tout au plus j'arrive à des solutions recommandant $TERMou tty.

Álex
la source

Réponses:

6

Eh bien, je suppose que je ferais remarquer que presque tous les terminaux de nos jours sont "virtuels" dans le sens où vous en parlez ... même si le terminal se trouve à l'autre bout d'un port série authentique. Je veux dire, l'époque des VT-100 , des terminaux Wyse et d'autres terminaux "physiques", "réels" est à peu près révolue!

Cela dit, supposons que vous souhaitiez détecter le type de prise en charge Unicode de votre terminal. Vous pouvez le faire en écrivant des caractères de test à is et en voyant ce qui se passe. (Vous pouvez faire un effort pour effacer les caractères de test après avoir écrit, mais l'utilisateur peut toujours les voir brièvement, ou les effacer peut ne pas fonctionner correctement en premier lieu.)

L'idée est de demander au terminal de vous indiquer la position de son curseur, de sortir un caractère de test, de demander à nouveau au terminal de vous indiquer sa position et de comparer les deux positions pour voir jusqu'où le curseur du terminal s'est déplacé.

Pour demander au terminal sa position, voir ici . Essentiellement:

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

Essayez de sortir "é". Ce caractère prend 2 octets en UTF-8 mais s'affiche dans une seule colonne à l'écran. Si vous détectez que la sortie "é" provoque le déplacement du curseur de 2 positions, alors le terminal n'a aucun support UTF-8 et a probablement sorti une sorte d'ordure. Si le curseur n'a pas bougé du tout, alors le terminal est probablement ASCII uniquement. S'il s'est déplacé de 1 position, alors félicitations, il peut probablement afficher des mots français.

Essayez de sortir "あ". Ce caractère prend 3 octets en UTF-8 mais s'affiche dans seulement deux colonnes à l'écran. Si le curseur se déplace de 0 ou 3, mauvaise nouvelle, comme ci-dessus. S'il se déplace de 1, il semble que le terminal prend en charge UTF-8 mais ne connaît pas les caractères larges (dans les polices à largeur fixe). S'il se déplace de 2 colonnes, tout va bien.

Je suis sûr qu'il existe d'autres caractères de sonde que vous pourriez émettre et qui pourraient conduire à des informations utiles. Je ne connais pas d'outil qui le fasse automatiquement.

Celada
la source
1
Merci pour la suggestion, Celada. Cependant, cela ne fonctionne pas: je vois correctement les positions avancées (1 pour é, 2 pour あ). La seule différence est que dans XI voir les vrais personnages tandis qu'en tty1 je vois un diamant. Je suppose donc que le terminal prend vraiment en charge utf-8, mais qu'il manque le caractère de la police utilisée.
Álex
J'ai vu maintenant la commande showconsolefont. Cela semblait une solution possible (avec -v, la police est de 512 caractères). Malheureusement, cela ne fonctionne que lorsque vous n'utilisez pas byobu. Dans ce dernier cas, il se trompe avec "Impossible d'obtenir un descripteur de fichier faisant référence à la console". Si je passe explicitement le tty (option -C), l'erreur devient "Impossible d'ouvrir / dev / pts / 37"
Álex
Soit dit en passant: script sh pour déterminer la largeur terminale d'une chaîne (mais ce n'est pas le sujet de cette question)
Gilles 'SO- arrête d'être méchant'
3

La véritable question d'OP est: quelles valeurs Unicode la console Linux prend-elle en charge et peut-elle être détectée pendant l'exécution screen. En principe, on peut le faire en récupérant la carte Unicode pour la console.

L' kbdarborescence source contient getunimap(et sa page de manuel). La page de manuel indique que

Le programme getunimap est ancien et obsolète. Il fait maintenant partie de setfont

ce qui n'est pas tout à fait vrai. setfonta une option qui fait à peu près la même chose:

   -ou file                                  
          Save previous Unicode map in file

Les différences:

  • setfontécrit dans un fichier, tandis qu'il getunimapécrit dans la sortie standard
  • getunimap montre le caractère qui serait mappé, en tant que commentaire.

Par exemple:

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  # ┗ 

contre

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 vous êtes en cours d'exécution screen(ou par exemple en cours d'exécution xtermet non sur la console), vous obtiendrez une erreur d'autorisations que vous pouvez contourner en utilisant sudo.

S'il m'arrive de savoir quelle police a été chargée, je peux vérifier cela (sans autorisations spéciales) en utilisant psfgettable, par exemple,

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

et voir les données de mappage qui setfontseraient utilisées pour charger la police (avec le mappage 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
...

Les deux getunimapet setfontdonnent les données non triées, tandis que psfgettablesemble être trié (ainsi que la combinaison de lignes pour les valeurs Unicode qui correspondent au même glyphe). Il y a donc des différences, mais l'information est accessible.

Lectures complémentaires (illustrant pourquoi vous ne pouvez pas utiliser showconsolefontpour résoudre ce problème):

Thomas Dickey
la source
Merci, Thomas, d'avoir clarifié ma question initiale et de m'avoir mis sur la bonne voie. J'essaierai d'obtenir une simple ligne à partir de vos informations et de revenir avec les résultats. L'utilisation sudon'est pas un obstacle pour mon cas d'utilisation.
Álex
Maintenant, c'est curieux: setfontne produit rien (ne crée pas le fichier donné ni ne génère d'erreur) dans les terminaux virtuels, mais fonctionne dans les terminaux réels comme prévu. C'est dans Ubuntu 16.04
Álex
2

Je suis tombé sur cette question alors que j'essayais d'accomplir la même chose, mais je ne voulais rien laisser à l'écran et lui faire définir une variable, alors j'ai mis ce qui suit dans un script shell que je source:

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
la source
1
Merci pour la contribution, Jeff. Malheureusement, je reçois toujours Y même dans la console de base: S
Álex