Detecta quanto de Unicode meu terminal suporta, mesmo através da tela

7

Aqui está o problema: Eu quero ser capaz de discernir se o meu terminal é capaz de unicode decente ou não, para usar alguns caracteres ou não, assim como os glances, que às vezes usam cores e outros sublinhados.

A motivação surge porque em qualquer tipo de terminal virtual eu recebo fontes decentes, mas eu entendo que o console básico do Linux tem um conjunto de caracteres de 256 ou 512 símbolos simultâneos, então você não pode esperar suporte completo a fontes.

No começo eu pensei que eu poderia usar $TERM ou tty, mas aqui está o problema: estou usando o byobu também, então $TERM é sempre "screen.linux". A saída de tty também não é muito reveladora: /dev/pts/<some number> em termos "reais" e virtuais.

$BYOBU_TTY também não ajuda, porque, por exemplo pode ser /dev/tty1 e quando a sessão é aberta em Ctrl + Alt + F1 , os caracteres não aparecem, mas ao anexar ao mesma sessão de algum termo X, eles mostram corretamente e ainda $BYOBU_TTY não muda. Além disso, gostaria de poder detectar isso sem presumir que o byobu está presente ou não.

Além disso, o locale é exibido em todos os casos en_US.UTF-8

No entanto, alguns relances (para nomear uma ferramenta específica que vejo detectando isso), mesmo dentro do byobu, usam saída diferente dependendo do terminal que estou anexando à sessão byobu.

Estou tendo problemas com o google porque terminal e tty parecem termos de pesquisa muito comuns. No máximo chego a soluções que recomendam $TERM ou tty.

    
por Álex 12.02.2015 / 00:48

3 respostas

5

Bem, primeiro eu acho que eu diria que praticamente todos os terminais atualmente são "virtuais" no sentido de que você fala ... mesmo que o terminal esteja do outro lado de uma porta serial autêntica. Quero dizer, os dias de VT-100 s,

Além disso, digamos que você queira detectar o tipo de suporte Unicode que seu terminal possui. Você pode fazer isso escrevendo caracteres de teste e vendo o que acontece. (Você pode fazer um esforço para apagar os caracteres de teste depois de escrever, mas o usuário ainda pode vê-los brevemente, ou apagá-los pode não funcionar corretamente em primeiro lugar.)

A idéia é pedir ao terminal que lhe informe a posição do cursor, imprima um caractere de teste, pergunte ao terminal novamente para informar sua posição e compare as duas posições para ver até onde o cursor do terminal se moveu.

Para solicitar ao terminal sua posição, consulte aqui . Essencialmente:

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

Tente produzir "é". Esse caractere leva 2 bytes em UTF-8, mas é exibido em apenas uma coluna na tela. Se você detectar que a saída "é" faz com que o cursor se mova por 2 posições, então o terminal não tem suporte UTF-8 e provavelmente produz algum tipo de lixo. Se o cursor não se moveu, então o terminal provavelmente é apenas ASCII. Se ele se moveu por 1 posição, então parabéns, provavelmente ele pode exibir palavras em francês.

Tente produzir "あ". Esse caractere leva 3 bytes em UTF-8, mas é exibido em apenas duas colunas na tela. Se o cursor se mover por 0 ou 3, más notícias, semelhantes às anteriores. Se ele se move por 1, então parece que o terminal suporta UTF-8, mas não sabe sobre caracteres largos (em fontes de largura fixa). Se se mover por 2 colunas, tudo é bom.

Tenho certeza de que há outros caracteres de sonda que você poderia emitir, o que levaria a informações úteis. Não tenho conhecimento de uma ferramenta que faz isso automaticamente.

    
por 12.02.2015 / 03:20
2
A pergunta real do

OP é: quais valores Unicode o console Linux suporta e quais podem ser detectados durante a execução de screen . Em princípio, pode-se fazer isso recuperando o mapa Unicode para o console.

A árvore da fonte kbd contém getunimap (e sua página de manual) . A página de manual diz que

The getunimap program is old and obsolete. It is now part of setfont

o que não é exatamente verdade. setfont tem uma opção que faz aproximadamente a mesma coisa :

   -ou file                                  
          Save previous Unicode map in file

As diferenças:

  • setfont grava em um arquivo, enquanto getunimap grava na saída padrão
  • getunimap mostra o caractere que seria mapeado, como um comentário.

Por exemplo:

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

Se você estiver executando em screen (ou, por exemplo, executando xterm e não no console), você receberá um erro de permissão que pode ser usado com sudo .

Se eu souber qual fonte foi carregada, posso verificar isso (sem permissões especiais) usando psfgettable , por exemplo,

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

e veja os dados de mapeamento que setfont usaria para carregar a fonte (com o mapeamento 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
...

Tanto getunimap como setfont fornecem os dados não classificados, enquanto psfgettable parece estar classificado (além de combinar linhas para valores Unicode que mapeiam para o mesmo glifo). Portanto, existem diferenças, mas a informação é acessível.

Leitura adicional (ilustrando porque você não pode usar showconsolefont para resolver este problema):

por 19.12.2016 / 02:17
1

Eu me deparei com essa questão enquanto tentava realizar a mesma coisa, mas não queria deixar nada na tela e definir uma variável, então coloquei o seguinte em um script de shell que eu sou:

function test_unicode {
  echo -ne "\xe2\x88\xb43[6n3[1K\r"
  read -d R foo
  echo -ne "3[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
    
por 17.12.2015 / 22:57