Xterm.js: Suporte a idiomas RTL

Criado em 13 jun. 2017  ·  17Comentários  ·  Fonte: xtermjs/xterm.js

Problema downstream: https://github.com/Microsoft/vscode/issues/28571

Quando aplicamos a largura do caractere Unicode em https://github.com/sourcelair/xterm.js/issues/467, isso quebrou os caracteres da linguagem RTL, pois agora eles são renderizados ao contrário (LTR). Poderíamos reverter isso para os intervalos de caracteres RTL apenas, mas devemos fazer a correção correta e inverter as strings para que eles realmente estejam na grade de caracteres, já que o novo modelo de seleção depende de todos os caracteres alinhados perfeitamente na grade https: // github. com / sourcelair / xterm.js / pull / 670

O ideal é que o refluxo de linha https://github.com/sourcelair/xterm.js/issues/622 seja feito antes disso, para que seja mais fácil alterar o conteúdo de várias linhas.

Terminal.app:

image

Código VS 1.13 (frases de aviso são invertidas):

image

@ mostafa69d @CherryDT algumas informações sobre os idiomas em questão seriam úteis:

  1. Onde as strings devem ser invertidas. Para hebraico / árabe / persa, reverter sequências contínuas inteiras de caracteres entre caracteres ascii?
  2. Como os personagens devem interagir com personagens como 0-9 ou pontuação?

Referências úteis:

arei18n arerenderer typenhancement

Comentários muito úteis

@Tyriar
Em primeiro lugar, vou dar-lhe uma breve perspectiva da língua árabe e persa que talvez te ajude (não tenho a certeza se o hebraico é o mesmo).
Nas línguas árabe e persa, os alfabetos são como "آ" "ب" "س" e assim por diante. E as palavras são feitas por esses alfabetos (obviamente) com uma regra muito diferente em comparação com, por exemplo, o inglês.
A diferença é que temos mais de uma forma para algum alfabeto como "س". A primeira forma é "س" e a segunda é "سـ", a outra é "ـسـ" e a última é "ـس". E qual é o uso dessas formas? Com base em onde o alfabeto em uma palavra aparece, a forma do alfabeto que usamos varia. Por exemplo, para o alfabeto mencionado "س", usamos a forma "سـ" quando uma palavra começa com esse alfabeto, como "سلام". Aqui está o problema e, na verdade, a diferença entre um idioma como o inglês e o persa ou árabe. Geramos palavras nesses idiomas conciliando as diferentes formas desses alfabetos (em alguns casos, os juntamos). Mais uma vez, destaco a seguinte regra: geramos essas palavras concatenando as formas, não os alfabetos (o que sempre significa alfabetos em inglês). Você pode ver alguns exemplos abaixo:
temos alfabetos "ک" "ن" "ا" "د" "ی"
Eu faço essas palavras apenas com os alfabetos mencionados: نادان, یاد, دکان
Então, para encerrar e dar a você uma pista do que aconteceu nas imagens que postei, o terminal divide as palavras em alfabetos e as reverte (então não se trata apenas de inverter). Dê uma olhada nas palavras que criei e nos alfabetos que mencionei antes. Agora, o terminal VS os mostra "separados" e "invertidos".

Formato correto: نادان Terminal: ن ا د ا ن
Formato correto: یاد Terminal: د ا ی
Formato correto: دکان Terminal: ن ا ک د

Agora suas perguntas:
Onde as strings devem ser invertidas. Para hebraico / árabe / persa, reverter sequências contínuas inteiras de caracteres entre caracteres ascii?
Não tenho nenhuma ideia sobre hebraico, mas em árabe e persa as sequências de caracteres devem virar quando encontram um caractere de espaço (A palavra separador é espaço) como este: "من در حال نوشتن هستم" mas ainda assim deve manter o "formas" e aderência necessária.

Como os personagens devem interagir com personagens como 0-9 ou pontuação?
Sobre números e pontuação, as regras são as mesmas do inglês e os números e sinais de pontuação seguem os caracteres. assim:
? من در سال "۱۳۶۹" به دنیا آمدم.
من در سال "1369" به دنیا آمدم.
Na verdade, uma sequência de personagens contendo personagens RTL e não RTL é uma história totalmente diferente e se você precisar de mais informações, posso elaborá-la.

PS 1:
Este link aqui é um código fonte que foi escrito para resolver o mesmo problema no PHP (com certeza nas versões antigas) você pode dar uma olhada
https://github.com/slashmili/php-gd-persian/blob/master/phpgd/fagd.php

PS 2:
Aqui está um recurso na wikipedia sobre os personagens persas
https://en.wikipedia.org/wiki/Persian_alphabet

PS 3:
Mais uma vez, devo mencionar que na versão anterior do VS Code estava tudo bem.

PS 4:
Sobre o problema de selecionar uma palavra contendo algum caractere LTR como
<p>اینجا را بخوانید</p> que @CherryDT mencionou, existem alguns pequenos bugs que não tenho problema com eles e encontrei soluções rápidas para eles. (Mas ainda se você precisar de alguma elaboração sobre eles, me avise)

Todos 17 comentários

Na verdade, é muito mais complicado e inclui statefulness e até mesmo espelhamento de certos personagens. Eu diria que é uma ciência própria. (E eu tenho o mais profundo respeito por aquelas pessoas que escreveram bibliotecas robustas de renderização de texto que lidam com todos os problemas BiDi adequadamente, então _Eu_ não tenho que mexer com isso, para ser honesto.)

Veja também:
https://en.wikipedia.org/wiki/Bi-directional_text (boa visão geral)
https://www.w3.org/International/articles/inline-bidi-markup/uba-basics
https://www.w3.org/International/tutorials/svg-tiny-bidi/ (a premissa inicial não está relacionada, mas explica algumas coisas melhor do que o link anterior)
https://github.com/fevangelou/doctype-mirror/tree/master/bidihowto/bidi-support-in-a-ui

EDIT: Eu acho que a maneira como a nova seleção funciona pode realmente ser inesperada porque vai se comportar de maneira diferente do próprio VSCode. Por exemplo, dado o texto "A música מדינת קומבינה me faz pensar", quando eu começar a selecionar "O" e terminar entre as duas palavras hebraicas, terei selecionado "A música מדינת", enquanto no console terei selecionado "A música קומבינה".

Consultar exemplo:
Image

No entanto, ainda será melhor do que como Sublime Text "funciona" da última vez que verifiquei, porque lá você verá uma coisa selecionada, mas copie outra, o que é muito chato.

@Tyriar
Em primeiro lugar, vou dar-lhe uma breve perspectiva da língua árabe e persa que talvez te ajude (não tenho a certeza se o hebraico é o mesmo).
Nas línguas árabe e persa, os alfabetos são como "آ" "ب" "س" e assim por diante. E as palavras são feitas por esses alfabetos (obviamente) com uma regra muito diferente em comparação com, por exemplo, o inglês.
A diferença é que temos mais de uma forma para algum alfabeto como "س". A primeira forma é "س" e a segunda é "سـ", a outra é "ـسـ" e a última é "ـس". E qual é o uso dessas formas? Com base em onde o alfabeto em uma palavra aparece, a forma do alfabeto que usamos varia. Por exemplo, para o alfabeto mencionado "س", usamos a forma "سـ" quando uma palavra começa com esse alfabeto, como "سلام". Aqui está o problema e, na verdade, a diferença entre um idioma como o inglês e o persa ou árabe. Geramos palavras nesses idiomas conciliando as diferentes formas desses alfabetos (em alguns casos, os juntamos). Mais uma vez, destaco a seguinte regra: geramos essas palavras concatenando as formas, não os alfabetos (o que sempre significa alfabetos em inglês). Você pode ver alguns exemplos abaixo:
temos alfabetos "ک" "ن" "ا" "د" "ی"
Eu faço essas palavras apenas com os alfabetos mencionados: نادان, یاد, دکان
Então, para encerrar e dar a você uma pista do que aconteceu nas imagens que postei, o terminal divide as palavras em alfabetos e as reverte (então não se trata apenas de inverter). Dê uma olhada nas palavras que criei e nos alfabetos que mencionei antes. Agora, o terminal VS os mostra "separados" e "invertidos".

Formato correto: نادان Terminal: ن ا د ا ن
Formato correto: یاد Terminal: د ا ی
Formato correto: دکان Terminal: ن ا ک د

Agora suas perguntas:
Onde as strings devem ser invertidas. Para hebraico / árabe / persa, reverter sequências contínuas inteiras de caracteres entre caracteres ascii?
Não tenho nenhuma ideia sobre hebraico, mas em árabe e persa as sequências de caracteres devem virar quando encontram um caractere de espaço (A palavra separador é espaço) como este: "من در حال نوشتن هستم" mas ainda assim deve manter o "formas" e aderência necessária.

Como os personagens devem interagir com personagens como 0-9 ou pontuação?
Sobre números e pontuação, as regras são as mesmas do inglês e os números e sinais de pontuação seguem os caracteres. assim:
? من در سال "۱۳۶۹" به دنیا آمدم.
من در سال "1369" به دنیا آمدم.
Na verdade, uma sequência de personagens contendo personagens RTL e não RTL é uma história totalmente diferente e se você precisar de mais informações, posso elaborá-la.

PS 1:
Este link aqui é um código fonte que foi escrito para resolver o mesmo problema no PHP (com certeza nas versões antigas) você pode dar uma olhada
https://github.com/slashmili/php-gd-persian/blob/master/phpgd/fagd.php

PS 2:
Aqui está um recurso na wikipedia sobre os personagens persas
https://en.wikipedia.org/wiki/Persian_alphabet

PS 3:
Mais uma vez, devo mencionar que na versão anterior do VS Code estava tudo bem.

PS 4:
Sobre o problema de selecionar uma palavra contendo algum caractere LTR como
<p>اینجا را بخوانید</p> que @CherryDT mencionou, existem alguns pequenos bugs que não tenho problema com eles e encontrei soluções rápidas para eles. (Mas ainda se você precisar de alguma elaboração sobre eles, me avise)

Depois de atualizar meu vscode, tudo revertido, Isso é muito ruim, por favor, resolva este problema
Eu quero fazer o downgrade, a versão Witch está ok?

@ mostafa69d felizmente em hebraico que mal existe. As letras hebraicas permanecem praticamente as mesmas em qualquer posição dentro de uma palavra, além de algumas letras que são כ que se transforma em ך, a seguir מ que se transforma em ם, a seguir נ que se transforma em ן, a seguir פ que se transforma em ף e finalmente צ que se transforma em ץ. Isso torna o hebraico mais fácil de formatar, eu acho.

No entanto, esses ainda são caracteres separados (em termos de codificação de caracteres) e sempre são exibidos da mesma forma. Eles não mudam de aparência quando movidos. (É função do escritor usar a letra certa - suave ou não - na posição certa.)

O problema com a divisão de caracteres é que quando eles são agrupados no intervalo um por um, ele exigirá conexão e não representará a forma (letras árabes).

Para resolver o problema, esses caracteres devem estar dentro de um intervalo ou não devem ser agrupados.

A lista do Unicode todas essas letras são
Árabe (0600–06FF, 255 caracteres)
Suplemento árabe (0750–077F, 48 caracteres)
Árabe Extended-A (08A0–08FF, 73 caracteres)
Formulários de apresentação em árabe-A (FB50 – FDFF, 611 caracteres)
Formulários B de apresentação em árabe (FE70 – FEFF, 141 caracteres)
Símbolos numéricos de Rumi (10E60–10E7F, 31 caracteres)
Símbolos alfabéticos matemáticos árabes (1EE00—1EEFF, 143 caracteres)
screen shot 2017-11-29 at 11 45 00 pm

leitura obrigatória: https://opensource.com/life/16/3/twisted-road-right-left-language-support

de https://github.com/Microsoft/vscode/issues/28571#issuecomment -307991443

você tem um exemplo de outro terminal que lida bem com isso?

O mlterm parece ser melhor do que o terminal médio (não baseado na web).
2018-11-15-023232_577x981_scrot
É cursivo, mas em alguns casos cortado, acho que pode ser resolvido mudando a fonte, este parágrafo foi copiado da Wikipedia, os caracteres azuis são a marca RTL, é assim que o vim os produz e o mlterm os renderiza em azul.

A API de junção de caracteres pode ser capaz de resolver isso, provavelmente poderíamos fazer todos os adjacentes arabic / hebrew / etc. caracteres Unicode se unem e são desenhados no mesmo glifo.

Pelo que vale a pena, o console de depuração funciona bem com textos RTL. Isso é o que eu tentei:
code
E esta é a saída no console de depuração:
debug
Mas o terminal ainda é o mesmo:
terminal

Estou usando o VS Code - Insiders v1.31.0.

@babakks Pelo que eu sei, apenas dois terminais no sistema Linux podem produzir RTL corretamente, konsole e mlterm , eles estão disponíveis em todos os repositórios das distros.

@ elieobeid7 @babakks Terminal de saída do Mac OS RTL corretamente

Faça um PR para consertar isso, se alguém quiser testar o branch, isso seria útil, já que não falo esses idiomas. https://github.com/xtermjs/xterm.js/pull/1899

Testar:

git clone https://github.com/Tyriar/xterm.js
cd xterm.js
git checkout 701_rtl_support
yarn
yarn watch

# another terminals
yarn start

Pode ser necessário que algumas dependências sejam instaladas https://github.com/Microsoft/node-pty#dependencies

Por favor, espere um pouco :)

Recentemente, estive trabalhando em estudar, avaliar documentos existentes e implementações de RTL em terminais e chegar a uma (rascunho) recomendação. Vou lançar em breve agora.

É muito mais complicado do que se poderia pensar. Um pouco de spoiler: se você começar a embaralhar os personagens de acordo com o algoritmo BiDi, torna-se literalmente, matematicamente provável, impossível ter uma experiência adequada de edição e visualização de texto com reconhecimento de BiDi (por exemplo, vim, emacs ...) no topo dessa plataforma . (E para responder aos comentários anteriores: não, konsole, mlterm e MacOS Terminal também não acertam.)

@egmontkob isso leva em consideração o fato de que conseguimos alavancar o suporte bidi do navegador? Tudo o que minha mudança faz é forçar sequências Unicode relacionadas a serem desenhadas juntas, não como caracteres separados. Provavelmente, isso está errado quando o cursor está sobre o caractere, mas parece funcionar de outra forma.

@Tyriar Desculpe, Tyriar, mas ainda está errado. Eu comentei sob o pedido de pull.
https://github.com/xtermjs/xterm.js/pull/1899#issuecomment -455333377

A especificação define como a tela precisa se parecer, depois de receber alguns dados. A especificação não importa qual seja o backend do emulador de terminal (por exemplo, uma tela gráfica ou um navegador (HTML DOM) ou outro emulador de terminal (tmux)), é tarefa do emulador de terminal implementar o comportamento especificado por quaisquer meios .

E um aspecto do comportamento especificado é que, em algumas circunstâncias, as células de caracteres precisam ser embaralhadas de acordo com o algoritmo BiDi (apenas para fins de exibição, não afetando o armazenamento real), porque essa é a única maneira razoável de obter utilitários simples como "cat "produzir a saída desejada; e em algumas outras circunstâncias as células não devem ser rearranjadas, porque essa é a única maneira do vim / emacs / qualquer um fazer seu próprio BiDi. Existem sequências de escape que controlam esse comportamento. E há muito mais nesta história do que isso.

Consulte o projeto de especificação BiDi publicado em https://terminal-wg.pages.freedesktop.org/bidi/ . Comentários, idéias de melhoria, etc. são bem-vindos no rastreador de problemas.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

LB-J picture LB-J  ·  3Comentários

chris-tse picture chris-tse  ·  4Comentários

zhangjie2012 picture zhangjie2012  ·  3Comentários

travisobregon picture travisobregon  ·  3Comentários

Mlocik97-issues picture Mlocik97-issues  ·  3Comentários