現在のコードはマルチバイト文字列をサポートしていません。たとえば、ASCII範囲を超えるUnicode文字を含む文字列です。 refreshLineの列シフトは、トルコ語の「Ş」のような2バイト文字に対して1ではなく2を返すstrlen()を使用して計算されます。
ライブラリは、列処理(上矢印、下矢印、文字の消去など)のバイト数ではなく、mbstowcs()またはその他の関数を使用して文字数を取得する必要があります。
また、これらの関数はLC_CTYPEに依存するため、ユーザーまたはlinenoiseを使用するアプリケーションは、setlocale(LC_ALL、 "")を呼び出して、アプリケーションのロケールをシステムロケールに設定する必要があります。
ありがとう。
参照: http :
utf-8をサポートしている私のフォークhttps://github.com/msteveb/linenoiseを見て
これらすべての機能が本当に必要ですか? 私はその内容にあまり詳しくありませんが、文字列の長さが文字列の文字数と同じであると想定されるstrlen()の代わりにmbstowcs()を使用することで、いくつかの奇妙な問題を簡単に修正しました。 しかし、バックスペース付きのワイド文字の削除を修正する方法が見つかりませんでした。
ここでのアプローチは、utf-8のシステムサポートへの依存を回避することです。 たとえば、ロケールをサポートせずにuClibcを実行しているシステムがありますが、シリアルポートを介してutf-8コンソールを問題なく実行できます。 もちろん、別のアプローチを取ることもできます。
同様の問題があります。 シェル実装のラインノイズを試してみました。 色付きのプロンプトが必要な場合は、エスケープコードが長さの計算に含まれることになります。
より単純で簡単な修正は、次のことです。
1)プロンプトの長さを自分で指定できるようにします。
2)プロンプトを出力した後、ターミナルコマンドを使用してカーソルの位置を抽出します(これが可能かどうかはわかりません)
これはmongoシェルのコードから見つけました。 私は常にますます多くのCLIツール(mongo、redis-cli、node)に悩まされています)マルチバイト文字があるとカーソルが不自然に動くのを使用します。 他の人がlinenoiseか何か他のものを使っているかどうかはわかりませんが、これが修正されることを望んでいます:-)
幅を自分で指定できるように変更されたラインノイズを作成したので、アプリケーションにとっては余分な作業ですが、少なくとも可能です。 約3ヶ月間問題なく使用しています。 おそらくプルリクエストに変えます。
フォークの「utf- 8support
ö (U+00F6)
ö (U+006F U+0308)
日本語
(「日本語」)私は最初にhttps://github.com/msteveb/linenoiseを試しました
こんにちは、私はこの問題で次のルートに行くことを考えています:
このようにして、ラインノイズの単純さはほとんど手つかずのままですが、オプションで、 C++
関数、標準の関数とは異なる他のユーザー提供の関数、またはラインノイズ自体に含まれている関数の両方でマルチバイト文字をサポートすることができます。プロジェクトはCであり、 @ yhiroseがすでに何
あなたにとって意味がありますか? ありがとう。
@antirez 、マルチバイトコードユーザーに注意を払ってくれてありがとう! あなたが提示したアイデアは私には完全に理にかなっています。 ラインノイズライブラリ自体が拡張性を提供できれば、他のマルチバイトエンコーディングサポートを簡単に追加できるので、私はさらに幸せです。
私のフォークでわかるように、「マルチバイト」サポートを有効にするための最も重要な概念は、テキストバッファの「バイト位置/幅」と画面の「列位置/幅」を明確に区別することです。 UTF-8の例を次に示します。
あ
(U + 3042): E3 81 82
(3バイト):ワイド(2列幅)ö
(U + 00F6): C3 B6
(2バイト):狭い(1列幅)ö
(U + 006F U + 0308): 6F CC 88
(3バイト):狭い(1列幅)違いがわかれば、マルチバイトコードを正しく処理するのは非常に簡単です。 1回目のコミットの変更からアイデアを把握できます。 2回目のコミットでも同じ原則をプロンプトテキストに適用しました。
注意が必要なのは、マルチラインモード処理コードだけです。 たとえば、最後の文字が広く、現在の行に1列しか残っていない場合、その幅の広い文字は残りのスペースに収まりません。 したがって、ワイド文字は次の行の先頭に表示する必要があります。 このコードはそれを処理します。
私がしたもう1つのことは、3番目のコミットで列の位置/幅を計算するときにすべてのANSIエスケープシーケンス文字をスキップ
近い将来、新しいAPIを見ることができて本当にうれしく思います。 この件についてご不明な点がございましたら、お気軽にお問い合わせください。 きっと素晴らしい仕事をしてくれると思います!!
設計目標に従ってラインノイズコードとUTF-8エンコーディングコードの依存関係について詳しく調べたところ、他のエンコーディングサポートを追加する場合に必要な関数は3つだけであることがわかりました。
調査に基づいて、ブランチを更新しました。 linenoiseheadとutf8-supportブランチの違いは次のとおりです。 ご覧のとおり、UTF-8固有のコードをすべてlinenoise.c
から完全に削除し、それらをencodings/utf8.h
とencodings/utf8.c
。 また、linenoise.hにlinenoiseSetEncodingFunctions
という1つの実験APIを追加して、ユーザーが独自のエンコード関数のセットを設定できるようにしました。 すべての機能が引き続き機能することを確認しました。
これが私の現在の実験的な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
とlinenoiseNextCharLen
は、戻り値としてバイト長を返し、列の長さをcol_len
パラメーターに設定します。 linenoiseReadCode
バイトをbuf
に読み取り、バイトを変換して、エンコード用の意味のある文字コードをc
パラメーターに設定します。
ユーザーがlinenoiseSetEncodingFunctions
呼び出さない場合、最終的に_default_実装を呼び出すことになります。 それらは単に_1バイト_を文字として扱います。
新しいエンコーディングAPIを設計するときに、この投稿がお役に立てば幸いです。 私は本当にそれを楽しみにしています!!
@yhiroseそれは素晴らしい作品です!!! :-)コードをチェックしてマージします。 これありがとう。
まだマージされていませんか?
@antirezそれをマージする上で何か進歩はありますか?
「ヒント」機能など、元のラインノイズに加えられた最近の変更に追いつくために、フォーク(https://github.com/yhirose/linenoise/tree/utf8-support)を変更しました。
@yhiroseありがとうございます。 あなたは良いコードをより良くしました! と私
仕事が楽に!
@sonophoto
2016年6月27日月曜日18:56:45-0700、yhiroseは次のように書いています。
I have modified my fork
(https://github.com/yhirose/linenoise/tree/utf8-support)追いつく
'ヒント'などの元のラインノイズに加えられた最近の変更
特徴。
—
このスレッドにサブスクライブしているため、これを受け取っています。
このメールに直接返信するか、GitHubで表示するか、スレッドをミュートしてください。
*
私のフォーク(https://github.com/yhirose/linenoise/tree/utf8-support)はUnicode9.0をサポートするようになりました。
@antirez近い将来、 @ yhiroseのマルチバイトサポートを統合するための自由な時間がありますか? それとも、それまで@yhiroseのフォークを使用するようにhttps://github.com/hoelzro/lua-linenoiseを切り替える必要がありますか? ✌️
私のフォーク(https://github.com/yhirose/linenoise/tree/utf8-support)はUnicode 11.0をサポートするようになり、 antirez / linenoiseで行われた最近の変更がすべて含まれています。
私のフォーク(https://github.com/yhirose/linenoise/tree/utf8-support)はUnicode12.1をサポートするようになりました。
私のフォーク(https://github.com/yhirose/linenoise/tree/utf8-support)はUnicode13.0をサポートするようになりました。
最も参考になるコメント
私のフォーク(https://github.com/yhirose/linenoise/tree/utf8-support)はUnicode 11.0をサポートするようになり、 antirez / linenoiseで行われた最近の変更がすべて含まれています。