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.
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:
ö (U+00F6)
ö (U+006F U+0308)
日本語
('Japonês')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:
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
. linenoiseReadCode
lê bytes 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.
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 .