Linenoise: Multibyte-Unterstützung hinzufügen

Erstellt am 23. Jan. 2012  ·  21Kommentare  ·  Quelle: antirez/linenoise

Der aktuelle Code unterstützt keine Multibyte-Strings, zB Strings mit Unicode-Zeichen außerhalb des ASCII-Bereichs. Die Spaltenverschiebungen für refreshLine werden mit strlen() berechnet, das 2 statt 1 für ein 2-Byte-Zeichen wie 'Ş' auf Türkisch zurückgibt.

Die Bibliothek sollte mbstowcs() oder andere Funktionen verwenden, um die Anzahl der Zeichen anstelle der Anzahl der Bytes für die Spaltenverarbeitung zu erhalten (Pfeil nach oben, unten, Löschen eines Zeichens usw.).

Und da diese Funktionen LC_CTYPE-abhängig sind, sollten entweder Sie oder die Anwendungen, die lineoise verwenden, setlocale(LC_ALL, "") aufrufen, um das Gebietsschema der Anwendung auf das Systemgebietsschema zu setzen.

Vielen Dank.

Hilfreichster Kommentar

Mein Fork (https://github.com/yhirose/linenoise/tree/utf8-support) unterstützt jetzt Unicode 11.0 und enthält alle kürzlich vorgenommenen Änderungen in antirez/linenoise .

Alle 21 Kommentare

Schauen Sie sich meinen Fork an, https://github.com/msteveb/linenoise , der utf-8 unterstützt

Brauchen Sie wirklich all diese Funktionen? Ich bin mit dem Zeug nicht ganz vertraut, aber ich habe einige der seltsamen Probleme leicht behoben, indem ich mbstowcs () anstelle von strlen () verwendet habe, wobei angenommen wird, dass die Länge der Zeichenfolge der Anzahl der Zeichen in der Zeichenfolge entspricht. Aber ich konnte keine Möglichkeit finden, das Löschen von breiten Zeichen mit der Rücktaste zu beheben.

Der Ansatz hier besteht darin, jegliche Abhängigkeit von der Systemunterstützung für utf-8 zu vermeiden. Zum Beispiel habe ich Systeme, auf denen uClibc ohne Locale-Unterstützung ausgeführt wird und die immer noch problemlos eine utf-8-Konsole über einen seriellen Port ausführen können. Natürlich können Sie gerne einen anderen Ansatz verfolgen.

Ich habe ein ähnliches Problem; Ich habe Zeilenrauschen für eine Shell-Implementierung ausprobiert. Wenn ich farbige Eingabeaufforderungen möchte, werden die Escape-Codes in die Längenberechnung einbezogen.

Eine einfachere, einfachere Lösung ist entweder:

1) Erlauben Sie, die Länge der Eingabeaufforderung selbst anzugeben.
2) Verwenden Sie Terminalbefehle, um die Position des Cursors nach der Ausgabe der Eingabeaufforderung zu extrahieren (nicht sicher, ob dies möglich ist)

Ich finde dies aus dem Code von Mongo Shell. Ich ärgere mich immer über immer mehr CLI-Tools (mongo, redis-cli, node)) die ich verwende, deren Cursor sich komisch bewegt, wenn es Multibyte-Zeichen gibt. Ich weiß nicht, ob die anderen Leinen oder etwas anderes verwenden, aber ich würde gerne sehen, dass dies behoben wird :-)

Ich habe ein modifiziertes Leinentuch gemacht, bei dem Sie die Breite selbst angeben können, also ist es für die Anwendung zusätzliche Arbeit, aber zumindest möglich; Ich benutze es seit etwa 3 Monaten ohne Probleme. Ich werde es vielleicht in einen Pull Request umwandeln.

Der Zweig 'utf-8 support' auf meinem Fork hat die folgenden UTF-8-Probleme behoben, die in der neuesten Linoise-Version 1.0 auftreten:

  • Multi-Byte-Zeichen: ö (U+00F6)
  • Mehrfachcode-Zeichen: ö (U+006F U+0308)
  • Breite Zeichen: 日本語 ('Japanisch')
  • Eingabeaufforderungstext mit den oben genannten Zeichen und farbigem ANSI-Escape-Text.

Ich habe zuerst https://github.com/msteveb/linenoise ausprobiert

Hallo, ich überlege, mit diesem Problem folgenden Weg zu gehen:

  1. Verwenden Sie @yhirose als Referenz, um zu überprüfen, wo die einfachen C-String-Funktionen durch
  2. Exportieren Sie eine API, die es dem lineoise-Benutzer ermöglicht, alternative Funktionen für die Berechnung der Stringlänge festzulegen. Stellen Sie die Funktion standardmäßig auf die einfachen C-Funktionen ein.
  3. Fügen Sie

Auf diese Weise erreichen wir, dass die Einfachheit von Leinoise fast unberührt bleibt, aber optional ist es möglich, Multi-Byte-Zeichen sowohl mit C++ Funktionen als auch mit anderen vom Benutzer bereitgestellten Funktionen, die sich von den Standardfunktionen unterscheiden, oder den in Leinoise selbst enthaltenen Funktionen zu unterstützen, wenn Sie project ist in C und Sie möchten nicht immer wieder neu schreiben, was @yhirose bereits geschrieben hat.

Macht das Sinn für dich? Vielen Dank.

@antirez , Vielen Dank, dass Sie den Benutzern des Multi-Byte-Codes Aufmerksamkeit geschenkt haben! Die Idee, die Sie vorgestellt haben, macht für mich absolut Sinn. Ich bin sogar noch glücklicher, denn wenn die Linenoise-Bibliothek selbst die Erweiterbarkeit bieten kann, könnten wir problemlos andere Unterstützung für die Multibyte-Codierung hinzufügen.

Wie Sie in meinem Fork sehen können, besteht das wichtigste Konzept zum Aktivieren der 'Multi-Byte'-Unterstützung darin, klar zwischen ' Byteposition/Breite ' im Textpuffer und ' Spaltenposition/Breite ' auf dem Bildschirm zu unterscheiden. Hier einige Beispiele in UTF-8:

  • (U+3042): E3 81 82 (3 Byte): Breit (2 Spaltenbreite)
  • ö (U+00F6): C3 B6 (2 Byte): Schmal (1 Spaltenbreite)
  • (U+006F U+0308): 6F CC 88 (3 Byte): Schmal (1 Spaltenbreite)

Sobald wir den Unterschied kennen, ist es ziemlich einfach, Multi-Byte-Code richtig zu handhaben. Sie können die Idee aus den Änderungen im 1. Commit erfassen. Dasselbe Prinzip habe ich auch beim zweiten Commit auf Eingabeaufforderungen angewendet.

Der einzige Ort, an dem wir vorsichtig sein müssen, ist der Code für die Behandlung des Multiline-Modus. Wenn beispielsweise das letzte Zeichen breit ist und in der aktuellen Zeile nur noch 1 Spalte vorhanden ist, passt dieses breite Zeichen nicht in den verbleibenden Platz. Das Breitzeichen muss also am Anfang der nächsten Zeile stehen. Dieser Code handhabt es.

Eine weitere Sache, die ich getan habe, ist, alle ANSI-Escape-Sequenzzeichen bei der Berechnung der Spaltenposition / -breite im 3. Commit zu überspringen. Diese Änderung ermöglicht es uns, Farbe im Eingabeaufforderungstext zu verwenden.

Ich freue mich sehr, die neue API in naher Zukunft zu sehen. Bitte lassen Sie mich wissen, wenn Sie Fragen zu diesem Thema haben. Ich bin sicher, dass Sie einen fantastischen Job machen werden!!

Nachdem ich gemäß Ihrem Designziel mehr über Abhängigkeiten zwischen dem Lininoise-Code und dem UTF-8-Codierungscode recherchiert hatte, stellte ich fest, dass nur drei Funktionen benötigt werden, wenn Sie andere Codierungsunterstützung hinzufügen.

Aufgrund der Recherche habe ich meinen Zweig aktualisiert. Hier ist der Unterschied zwischen dem Linenoise-Kopf und dem UTF8-Support-Zweig . Wie Sie dort sehen konnten, habe ich den gesamten UTF-8-spezifischen Code vollständig aus linenoise.c und in encodings/utf8.h und encodings/utf8.c abgelegt. Außerdem habe ich eine Experiment-API namens linenoiseSetEncodingFunctions auf lineoise.h hinzugefügt, damit Benutzer ihre eigenen Codierungsfunktionen einstellen können. Ich habe bestätigt, dass alle Funktionen noch funktionieren.

Hier ist ein Ausschnitt meiner aktuellen experimentellen API:

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 und linenoiseNextCharLen geben die Bytelänge als Rückgabewert zurück und setzen die Spaltenlänge auf den Parameter col_len . linenoiseReadCode liest Bytes in buf , konvertiert die Bytes und setzt einen aussagekräftigen Zeichencode für die Kodierung auf den Parameter c .

Wenn Benutzer linenoiseSetEncodingFunctions nicht aufrufen, werden _default_-Implementierungen aufgerufen. Sie behandeln einfach _ein Byte_ als Zeichen.

Ich hoffe, der Beitrag ist hilfreich, wenn Sie die neue Codierungs-API entwerfen. Ich freue mich schon sehr!!

@yhirose das ist eine fantastische Arbeit!!! :-) Ich werde den Code überprüfen und zusammenführen. Danke dafür.

Noch nicht zusammengeführt?

@antirez irgendwelche Fortschritte beim Zusammenführen?

Ich habe meinen Fork (https://github.com/yhirose/linenoise/tree/utf8-support) modifiziert, um die jüngsten Änderungen am ursprünglichen Linenoise wie die Funktion "Hinweise" einzuholen.

Vielen Dank @yhirose. Sie haben guten Code besser gemacht! und mein
Arbeit leichter!

@sonophoto

Am Montag, 27. Juni 2016, 18:56:45 -0700, schrieb yhirose:

   I have modified my fork 

(https://github.com/yhirose/linenoise/tree/utf8-support) um aufzuholen
mit den jüngsten Änderungen, die im ursprünglichen Leinenrausch vorgenommen wurden, wie z.B. 'Hinweise'
Besonderheit.

Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

*

Mein Fork (https://github.com/yhirose/linenoise/tree/utf8-support) unterstützt jetzt Unicode 9.0.

@antirez Werden Sie in naher Zukunft Freizeit haben , um die Multi-Byte-Unterstützung von https://github.com/hoelzro/lua-linenoise wechseln, um bis dahin den Fork von @yhirose zu verwenden? ️

Mein Fork (https://github.com/yhirose/linenoise/tree/utf8-support) unterstützt jetzt Unicode 11.0 und enthält alle kürzlich vorgenommenen Änderungen in antirez/linenoise .

Mein Fork (https://github.com/yhirose/linenoise/tree/utf8-support) unterstützt jetzt Unicode 12.1.

Mein Fork (https://github.com/yhirose/linenoise/tree/utf8-support) unterstützt jetzt Unicode 13.0.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

fatcerberus picture fatcerberus  ·  5Kommentare

denisvm picture denisvm  ·  9Kommentare

ghost picture ghost  ·  4Kommentare

JelteF picture JelteF  ·  8Kommentare

krux02 picture krux02  ·  8Kommentare