Linenoise: Adicionar suporte multibyte

Criado em 23 jan. 2012  ·  21Comentários  ·  Fonte: antirez/linenoise

O código atual não tem suporte para strings multibyte, por exemplo, strings com caracteres Unicode além do intervalo ASCII. Os deslocamentos de coluna para refreshLine são calculados usando strlen () que retorna 2 em vez de 1 para um caractere de 2 bytes como 'Ş' em turco.

A biblioteca deve usar mbstowcs () ou outras funções para obter o número de caracteres em vez do número de bytes para o processamento da coluna (setas para cima, para baixo, apagando um caractere, etc.).

E também como essas funções são dependentes de LC_CTYPE, você ou os aplicativos que usam linenoise devem chamar setlocale (LC_ALL, "") para definir a localidade do aplicativo para a localidade do sistema.

Obrigado.

Comentários muito úteis

Meu fork (https://github.com/yhirose/linenoise/tree/utf8-support) agora suporta Unicode 11.0 e inclui todas as mudanças recentes feitas no antirez / linenoise .

Todos 21 comentários

Dê uma olhada no meu fork, https://github.com/msteveb/linenoise , que tem suporte para utf-8

Você realmente precisa de todas essas funções? Não estou muito familiarizado com as coisas, mas resolvi facilmente alguns dos problemas estranhos usando mbstowcs () em vez de strlen () onde o comprimento da string é considerado equivalente ao número de caracteres na string. Mas não consegui encontrar uma maneira de corrigir a exclusão de caracteres largos com backspace.

A abordagem aqui é evitar qualquer dependência de suporte do sistema para utf-8. Por exemplo, eu tenho sistemas executando uClibc sem suporte de localidade que ainda podem executar um console utf-8 em uma porta serial. É claro que você pode adotar uma abordagem diferente.

Eu tenho um problema semelhante; Experimentei ruído de linha para uma implementação de shell. Se eu quiser prompts coloridos, os códigos de escape acabam sendo incluídos no cálculo do comprimento.

Uma solução mais simples e fácil é cada um:

1) permita que você mesmo especifique o comprimento do prompt.
2) usar comandos de terminal para extrair a posição do cursor após a saída do prompt (não tenho certeza se isso é possível)

Acho isso no código do shell do mongo. Sempre fico incomodado com mais e mais ferramentas CLI (mongo, redis-cli, node)) que uso o cursor que se move de maneira estranha quando há caracteres multibyte. Não sei se os outros estão usando ruído de linha ou outra coisa, mas gostaria que isso fosse corrigido :-)

Fiz um ruído de linha modificado que permite que você especifique a largura por conta própria, então é um trabalho extra para o aplicativo, mas pelo menos possível; Estou usando há cerca de 3 meses sem problemas. Vou transformá-lo em um pedido de pull, talvez.

O branch 'suporte a utf-8' em meu fork corrigiu os seguintes problemas UTF-8 que aparecem na última versão 1.0 do linenoise:

  • Caracteres multibyte: ö (U+00F6)
  • Caracteres multicódigos: ö (U+006F U+0308)
  • Caracteres largos: 日本語 ('Japonês')
  • Texto de prompt incluindo os caracteres acima e texto colorido com escape ANSI.

Tentei primeiro https://github.com/msteveb/linenoise. Mas não é baseado no mais recente ruído de linha, que suporta o fantástico modo multilinha. Também não suporta caracteres CJK largos e caracteres multicódigo ...

Olá, estou pensando em seguir o seguinte caminho com este problema:

  1. Use @yhirose como uma referência para verificar onde as funções de string simples C devem ser substituídas por funções com vários bytes.
  2. Exporte uma API que permite ao usuário de ruído de linha definir funções alternativas para cálculos de comprimento de string. Defina a função para as funções C simples como padrão.
  3. Inclua o código @yhirose como um arquivo separado que você pode adicionar ao seu aplicativo, chamando as novas funções de linenoise para definir as funções de comprimento, a fim de ter suporte a vários bytes.

Desta forma, obtemos que a simplicidade do ruído de linha permanece quase intacta, mas opcionalmente é possível suportar caracteres de vários bytes tanto com funções C++ , outras funções fornecidas pelo usuário diferentes das padrão, ou aquelas incluídas no próprio ruído de linha se seu projeto está em C e você não quer reescrever o que @yhirose já escreveu novamente e novamente.

Faz sentido para você? Obrigado.

@antirez , Obrigado por prestar atenção aos usuários do código multibyte! A ideia que você apresentou faz totalmente sentido para mim. Estou ainda mais feliz porque, se a própria biblioteca de ruído de linha pode fornecer a extensibilidade, poderíamos facilmente adicionar outro suporte de codificação multibyte.

Como você pode ver em meu fork, o conceito mais importante para habilitar o suporte a 'vários bytes' é fazer uma distinção clara entre ' posição / largura do byte ' no buffer de texto e ' posição / largura da coluna ' na tela. Aqui estão alguns exemplos em UTF-8:

  • (U + 3042): E3 81 82 (3 bytes): Largo (largura de 2 colunas)
  • ö (U + 00F6): C3 B6 (2 bytes): Estreito (largura de 1 coluna)
  • (U + 006F U + 0308): 6F CC 88 (3 bytes): Estreito (largura de 1 coluna)

Depois de sabermos a diferença, é muito fácil lidar com o código multibyte corretamente. Você pode captar a ideia das mudanças no primeiro commit . Eu apliquei o mesmo princípio ao prompt text no segundo commit também.

O único lugar onde precisamos ter cuidado é o código de manipulação do modo multilinha. Por exemplo, quando o último caractere é largo e há apenas 1 coluna restante na linha atual, esse caractere largo não cabe no espaço restante. Portanto, o caractere largo deve ser exibido no início da próxima linha. Este código trata disso.

Mais uma coisa que fiz foi pular todos os caracteres da sequência de escape ANSI ao calcular a posição / largura da coluna no terceiro commit . Essa mudança nos permite usar cores no texto do prompt.

Estou muito animado para ver a nova API em um futuro próximo. Entre em contato se tiver alguma dúvida sobre esse assunto. Tenho certeza que você fará um trabalho fantástico !!

Depois de pesquisar mais sobre dependências entre o código de ruído de linha e o código de codificação UTF-8 de acordo com seu objetivo de design, percebi que apenas três funções são necessárias ao adicionar outro suporte de codificação.

Com base na pesquisa, atualizei meu ramo. Aqui está a diferença entre a cabeça do linenoise e o ramo de suporte do utf8 . Como você pode ver lá, eu me livrei de todo o código específico UTF-8 de linenoise.c e os coloquei em encodings/utf8.h e encodings/utf8.c . Além disso, adicionei uma API de experimento chamada linenoiseSetEncodingFunctions em linenoise.h, para que os usuários pudessem definir seu próprio conjunto de funções de codificação. Confirmei que todas as funcionalidades ainda funcionam.

Aqui está um snippet da minha API experimental atual:

typedef size_t (linenoisePrevCharLen)(const char *buf, size_t buf_len, size_t pos, size_t *col_len);
typedef size_t (linenoiseNextCharLen)(const char *buf, size_t buf_len, size_t pos, size_t *col_len);
typedef size_t (linenoiseReadCode)(int fd, char *buf, size_t buf_len, int* c);

void linenoiseSetEncodingFunctions(
    linenoisePrevCharLen *prevCharLenFunc,
    linenoiseNextCharLen *nextCharLenFunc,
    linenoiseReadCode *readCodeFunc);

linenoisePrevCharLen e linenoiseNextCharLen retornam o comprimento do byte como o valor de retorno e definem o comprimento da coluna para o parâmetro col_len . linenoiseReadCodebytes em buf , converte os bytes e define um código de caractere significativo para a codificação no parâmetro c .

Se os usuários não chamarem linenoiseSetEncodingFunctions , ele acabará chamando implementações _default_. Eles simplesmente tratam _um byte_ como um caractere.

Espero que a postagem seja útil ao projetar a nova API de codificação. Estou realmente ansioso por isso !!

@yhirose é um trabalho fantástico !!! :-) Vou verificar o código e mesclá-lo. Obrigado por isso.

Ainda não foi mesclado?

@antirez algum progresso na fusão?

Eu modifiquei meu fork (https://github.com/yhirose/linenoise/tree/utf8-support) para acompanhar as mudanças recentes feitas no linenoise original, como o recurso de 'dicas'.

Muito obrigado @yhirose. Você tornou um bom código melhor! e meu
trabalho mais fácil!

@sonophoto

Na segunda-feira, 27 de junho de 2016 18:56:45 -0700, yhirose escreveu:

   I have modified my fork 

(https://github.com/yhirose/linenoise/tree/utf8-support) para acompanhar
com as mudanças recentes feitas no ruído de linha original, como 'dicas'
recurso.
-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

*

Meu fork (https://github.com/yhirose/linenoise/tree/utf8-support) agora suporta Unicode 9.0.

@antirez Você terá tempo livre em um futuro próximo para combinar o suporte multi-byte de https://github.com/hoelzro/lua-linenoise para usar o fork de @yhirose até então? ✌️

Meu fork (https://github.com/yhirose/linenoise/tree/utf8-support) agora suporta Unicode 11.0 e inclui todas as mudanças recentes feitas no antirez / linenoise .

Meu fork (https://github.com/yhirose/linenoise/tree/utf8-support) agora suporta Unicode 12.1.

Meu fork (https://github.com/yhirose/linenoise/tree/utf8-support) agora suporta Unicode 13.0.

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

Questões relacionadas

denisvm picture denisvm  ·  9Comentários

JelteF picture JelteF  ·  8Comentários

ghost picture ghost  ·  4Comentários

fatcerberus picture fatcerberus  ·  5Comentários

krux02 picture krux02  ·  8Comentários