Linenoise: Agregar soporte multibyte

Creado en 23 ene. 2012  ·  21Comentarios  ·  Fuente: antirez/linenoise

El código actual no admite cadenas multibyte, por ejemplo, cadenas que tienen caracteres Unicode más allá del rango ASCII. Los cambios de columna para refreshLine se calculan usando strlen () que devuelve 2 en lugar de 1 para un carácter de 2 bytes como 'Ş' en turco.

La biblioteca debe usar mbstowcs () u otras funciones para obtener el número de caracteres en lugar del número de bytes para el procesamiento de columnas (flechas arriba, abajo, borrar un carácter, etc.).

Y también como esas funciones dependen de LC_CTYPE, tanto usted como las aplicaciones que usan linenoise deben llamar a setlocale (LC_ALL, "") para establecer la configuración regional de la aplicación en la configuración regional del sistema.

Gracias.

Comentario más útil

Mi bifurcación (https://github.com/yhirose/linenoise/tree/utf8-support) ahora es compatible con Unicode 11.0 e incluye todos los cambios recientes realizados en antirez / linenoise .

Todos 21 comentarios

Eche un vistazo a mi bifurcación, https://github.com/msteveb/linenoise , que tiene soporte para utf-8

¿Realmente necesitas todas esas funciones? No estoy muy familiarizado con las cosas, pero solucioné fácilmente algunos de los problemas extraños usando mbstowcs () en lugar de strlen () donde se supone que la longitud de la cadena es equivalente a la cantidad de caracteres en la cadena. Pero no pude encontrar la manera de solucionar la eliminación de caracteres anchos con retroceso.

El enfoque aquí es evitar cualquier dependencia del soporte del sistema para utf-8. Por ejemplo, tengo sistemas que ejecutan uClibc sin soporte de configuración regional que aún pueden ejecutar felizmente una consola utf-8 a través de un puerto serie. Por supuesto, puede adoptar un enfoque diferente.

Tengo un problema similar; Probé line-noise para una implementación de shell. Si quiero mensajes de colores, los códigos de escape terminan incluyéndose en el cálculo de la longitud.

Una solución más simple y fácil es hacer lo siguiente:

1) permita que usted mismo especifique la longitud del mensaje.
2) use comandos de terminal para extraer la posición del cursor después de mostrar el mensaje (no estoy seguro de si esto es posible)

Encuentro esto en el código de mongo shell. Siempre me molestan más y más herramientas CLI (mongo, redis-cli, node)) que uso cuyo cursor se mueve de manera extraña cuando hay caracteres multibyte. No sé si los demás están usando linenoise o algo más, pero me gustaría ver que esto se solucione :-)

Hice una linenoise modificada que le permite especificar el ancho usted mismo, por lo que es un trabajo adicional para la aplicación, pero al menos es posible; Lo he estado usando durante aproximadamente 3 meses sin problemas. Lo convertiré en una solicitud de extracción, tal vez.

La rama 'utf-8 support' en mi bifurcación solucionó los siguientes problemas de UTF-8 que aparecen en la última versión 1.0 de linenoise:

  • Caracteres de varios bytes: ö (U+00F6)
  • Caracteres de varios códigos: ö (U+006F U+0308)
  • Caracteres anchos: 日本語 ('japonés')
  • Texto de solicitud que incluye los caracteres anteriores y texto de color de escape ANSI.

Primero probé https://github.com/msteveb/linenoise. Pero no se basa en la última linenoise que admite el fantástico modo multilínea. Además, no admite caracteres anchos CJK y caracteres de código múltiple ...

Hola, estoy pensando en seguir la siguiente ruta con este problema:

  1. Use @yhirose como referencia para verificar dónde las funciones de cadena simple de C deben ser sustituidas por funciones
  2. Exporte una API que permita al usuario de linenoise establecer funciones alternativas para cálculos de longitud de cadena. Establezca la función en las funciones C simples como predeterminadas.
  3. Incluya el código @yhirose como un archivo separado que puede agregar a su aplicación, llamando a las nuevas funciones de linenoise para establecer las funciones de longitud, con el fin de tener soporte multibyte.

De esta manera obtenemos que la simplicidad de linenoise permanece casi intacta, pero opcionalmente es posible admitir caracteres de varios bytes con funciones C++ , funciones proporcionadas por otros usuarios diferentes de las estándar, o las incluidas en linenoise si su El proyecto está en C y no quieres volver a escribir lo que @yhirose ya escribió una y otra vez.

¿Tiene sentido para ti? Gracias.

@antirez , ¡Gracias por prestar atención a los usuarios de códigos

Como puede ver en mi bifurcación, el concepto más importante para habilitar el soporte de 'múltiples bytes' es hacer una clara distinción entre ' posición / ancho de byte ' en el búfer de texto y ' posición / ancho de columna ' en la pantalla. A continuación, se muestran algunos ejemplos en UTF-8:

  • (U + 3042): E3 81 82 (3 bytes): Ancho (2 columnas de ancho)
  • ö (U + 00F6): C3 B6 (2 bytes): Estrecho (1 ancho de columna)
  • (U + 006F U + 0308): 6F CC 88 (3 bytes): Estrecho (1 ancho de columna)

Una vez que nos damos cuenta de la diferencia, es bastante fácil manejar correctamente el código multibyte. Puede captar la idea de los cambios en la primera confirmación . También apliqué el mismo principio al texto de solicitud en la segunda confirmación .

El único lugar donde debemos tener cuidado es el código de manejo del modo multilínea. Por ejemplo, cuando el último carácter es ancho y solo queda 1 columna en la fila actual, ese carácter ancho no se ajusta al espacio restante. Por lo tanto, el carácter ancho debe mostrarse al comienzo de la siguiente línea. Este código lo maneja.

Una cosa más que hice fue omitir todos los caracteres de la secuencia de escape ANSI al calcular la posición / ancho de la columna en

Estoy muy emocionado de ver la nueva API en un futuro próximo. Por favor, avíseme si tiene alguna pregunta sobre este asunto. Estoy seguro de que harás un trabajo fantástico !!

Después de investigar más sobre las dependencias entre el código linenoise y el código de codificación UTF-8 de acuerdo con su objetivo de diseño, me di cuenta de que solo se necesitan tres funciones al agregar otro soporte de codificación.

Basado en la investigación, he actualizado mi rama. Aquí está la diferencia entre el cabezal linenoise y la rama utf8-support . Como puede ver allí, me deshice de todo el código específico UTF-8 por completo de linenoise.c y los puse en encodings/utf8.h y encodings/utf8.c . También agregué una API de experimento llamada linenoiseSetEncodingFunctions en linenoise.h, para que los usuarios pudieran configurar su propio conjunto de funciones de codificación. Confirmé que todas las funcionalidades aún funcionan.

Aquí hay un fragmento de mi API experimental actual:

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 y linenoiseNextCharLen devuelven la longitud del byte como valor devuelto y establecen la longitud de la columna en el parámetro col_len . linenoiseReadCode lee bytes en buf , convierte los bytes y establece un código de carácter significativo para la codificación en el parámetro c .

Si los usuarios no llaman a linenoiseSetEncodingFunctions , terminará llamando a implementaciones _default_. Simplemente manejan _un byte_ como un carácter.

Espero que la publicación sea útil cuando diseñe la nueva API de codificación. ¡¡Lo estoy deseando!!

@yhirose, ¡ es un trabajo fantástico! :-) Voy a comprobar el código y fusionarlo. Gracias por esto.

¿Aún no te has fusionado?

@antirez ¿ algún progreso en la fusión?

He modificado mi bifurcación (https://github.com/yhirose/linenoise/tree/utf8-support) para ponerme al día con los cambios recientes realizados en la linenoise original, como la función 'sugerencias'.

Muchas gracias @yhirose. ¡Has mejorado el buen código! y mi
trabajo más fácil!

@sonophoto

El lunes, 27 de junio de 2016 18:56:45 -0700, yhirose escribió:

   I have modified my fork 

(https://github.com/yhirose/linenoise/tree/utf8-support) para ponerse al día
con los cambios recientes realizados en la linenoise original, como 'sugerencias'
característica.
-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.

*

Mi bifurcación (https://github.com/yhirose/linenoise/tree/utf8-support) ahora es compatible con Unicode 9.0.

@antirez ¿Tendrá tiempo libre en un futuro cercano para fusionar el soporte multibyte de https://github.com/hoelzro/lua-linenoise para usar la bifurcación de @yhirose hasta entonces? ✌️

Mi bifurcación (https://github.com/yhirose/linenoise/tree/utf8-support) ahora es compatible con Unicode 11.0 e incluye todos los cambios recientes realizados en antirez / linenoise .

Mi bifurcación (https://github.com/yhirose/linenoise/tree/utf8-support) ahora es compatible con Unicode 12.1.

Mi bifurcación (https://github.com/yhirose/linenoise/tree/utf8-support) ahora es compatible con Unicode 13.0.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

krux02 picture krux02  ·  8Comentarios

ghost picture ghost  ·  4Comentarios

fatcerberus picture fatcerberus  ·  5Comentarios

denisvm picture denisvm  ·  9Comentarios

JelteF picture JelteF  ·  8Comentarios