Linenoise: Tambahkan dukungan multibyte

Dibuat pada 23 Jan 2012  ·  21Komentar  ·  Sumber: antirez/linenoise

Kode saat ini tidak memiliki dukungan untuk string multibyte, misalnya string yang memiliki karakter unicode di luar jangkauan ASCII. Pergeseran kolom untuk refreshLine dihitung menggunakan strlen() yang mengembalikan 2 alih-alih 1 untuk karakter 2-byte seperti 'Ş' dalam bahasa Turki.

Pustaka harus menggunakan mbstowcs() atau fungsi lain untuk mendapatkan jumlah karakter alih-alih jumlah byte untuk pemrosesan kolom (panah atas, bawah, menghapus karakter, dll.).

Dan juga karena fungsi-fungsi tersebut bergantung pada LC_CTYPE, Anda atau aplikasi yang menggunakan linenoise harus memanggil setlocale(LC_ALL, "") untuk menyetel lokal aplikasi ke lokal sistem.

Terima kasih.

Komentar yang paling membantu

Garpu saya (https://github.com/yhirose/linenoise/tree/utf8-support) sekarang mendukung Unicode 11.0 dan mencakup semua perubahan terbaru yang dibuat di antirez/linenoise .

Semua 21 komentar

Lihatlah garpu saya, https://github.com/msteveb/linenoise , yang memiliki dukungan untuk utf-8

Apakah Anda benar-benar membutuhkan semua fungsi itu? Saya tidak begitu akrab dengan hal-hal itu tetapi saya dengan mudah memperbaiki beberapa masalah aneh dengan menggunakan mbstowcs() alih-alih strlen() di mana panjang string diasumsikan setara dengan jumlah karakter dalam string. Tetapi saya tidak dapat menemukan cara untuk memperbaiki penghapusan karakter lebar dengan spasi mundur ..

Pendekatan di sini adalah untuk menghindari ketergantungan pada dukungan sistem untuk utf-8. Sebagai contoh, saya memiliki sistem yang menjalankan uClibc tanpa dukungan lokal yang masih dapat dengan senang hati menjalankan konsol utf-8 melalui port serial. Tentu saja Anda dipersilakan untuk mengambil pendekatan yang berbeda.

Saya memiliki masalah serupa; Saya mencoba line-noise untuk implementasi shell. Jika saya ingin prompt berwarna, kode pelarian akhirnya dimasukkan dalam perhitungan panjang.

Perbaikan yang lebih sederhana dan lebih mudah adalah dengan:

1) izinkan menentukan sendiri panjang prompt.
2) gunakan perintah terminal untuk mengekstrak posisi kursor setelah mengeluarkan prompt (tidak yakin apakah ini mungkin)

Saya menemukan ini dari kode mongo Shell. Saya selalu terganggu oleh semakin banyak alat CLI (mongo, redis-cli, node)) yang saya gunakan kursornya bergerak aneh ketika ada karakter multibyte. Saya tidak tahu apakah yang lain menggunakan linenoise atau yang lainnya, tetapi saya ingin ini diperbaiki :-)

Saya telah membuat linenoise yang dimodifikasi yang memungkinkan Anda menentukan sendiri lebarnya, jadi ini pekerjaan ekstra untuk aplikasi, tetapi setidaknya mungkin; Saya telah menggunakannya selama sekitar 3 bulan tanpa masalah. Saya akan mengubahnya menjadi permintaan tarik, mungkin.

Cabang 'utf-8 support' di fork saya memperbaiki masalah UTF-8 berikut yang muncul di linenoise versi 1.0 terbaru:

  • Karakter multi-byte: ö (U+00F6)
  • Karakter multi-kode: ö (U+006F U+0308)
  • Karakter lebar: 日本語 ('Jepang')
  • Teks prompt termasuk karakter di atas dan ANSI lolos dari teks berwarna.

Saya pertama kali mencoba https://github.com/msteveb/linenoise. Tapi itu tidak didasarkan pada linenoise terbaru yang mendukung mode multiline yang fantastis. Juga tidak mendukung karakter lebar CJK dan karakter multi-kode ...

Halo, saya sedang berpikir untuk mengambil rute berikut dengan masalah ini:

  1. Gunakan @yhirose sebagai referensi untuk memeriksa di mana fungsi string biasa C harus diganti dengan yang sadar multi-byte.
  2. Ekspor API yang memungkinkan pengguna linenoise menyetel fungsi alternatif untuk penghitungan panjang string. Atur fungsi ke fungsi C biasa sebagai default.
  3. Sertakan kode @yhirose sebagai file terpisah yang dapat Anda tambahkan ke aplikasi Anda, panggil fungsi baru linenoise untuk mengatur fungsi panjang, agar memiliki dukungan multi-byte.

Dengan cara ini kami memperoleh bahwa kesederhanaan linenoise tetap hampir tidak tersentuh, tetapi secara opsional dimungkinkan untuk mendukung karakter multi byte baik dengan fungsi C++ , fungsi yang disediakan pengguna lain yang berbeda dari yang standar, atau yang termasuk dalam linenoise itu sendiri jika Anda proyek ada di C dan Anda tidak ingin menulis ulang apa yang sudah ditulis @yhirose berulang kali.

Masuk akal bagi Anda? Terima kasih.

@antirez , Terima kasih telah memperhatikan pengguna kode multi-byte! Gagasan yang Anda sajikan benar-benar masuk akal bagi saya. Saya bahkan lebih bahagia karena jika perpustakaan linenoise itu sendiri dapat memberikan ekstensibilitas, kami dapat dengan mudah menambahkan dukungan pengkodean multi-byte lainnya.

Seperti yang Anda lihat di fork saya, konsep paling penting untuk mengaktifkan dukungan 'multi byte' adalah membuat perbedaan yang jelas antara ' byte position/width ' dalam buffer teks dan ' column position/width ' di layar. Berikut adalah beberapa contoh di UTF-8:

  • (U+3042): E3 81 82 (3 byte): Lebar (lebar 2 kolom)
  • ö (U+00F6): C3 B6 (2 byte): Sempit (lebar 1 kolom)
  • (U+006F U+0308): 6F CC 88 (3 byte): Sempit (lebar 1 kolom)

Setelah kita mengetahui perbedaannya, cukup mudah untuk menangani kode multi-byte dengan benar. Anda dapat memahami ide dari perubahan pada komit pertama . Saya menerapkan prinsip yang sama untuk meminta teks di komit ke-2 juga.

Satu-satunya tempat di mana kita perlu berhati-hati adalah kode penanganan mode multiline. Misalnya, ketika karakter terakhir lebar dan hanya tersisa 1 kolom pada baris saat ini, karakter lebar tersebut tidak sesuai dengan ruang yang tersisa. Jadi karakter lebar harus ditampilkan di awal baris berikutnya. Kode ini menanganinya.

Satu hal lagi yang saya lakukan adalah melewatkan semua karakter urutan pelarian ANSI saat menghitung posisi/lebar kolom di komit ke-3 . Perubahan ini memungkinkan kita untuk menggunakan warna dalam teks prompt.

Saya sangat senang melihat API baru dalam waktu dekat. Harap beri tahu saya jika Anda memiliki pertanyaan tentang masalah ini. Saya yakin Anda akan melakukan pekerjaan yang fantastis!!

Setelah meneliti lebih lanjut tentang ketergantungan antara kode linenoise dan kode penyandian UTF-8 sesuai dengan tujuan desain Anda, saya menyadari bahwa hanya tiga fungsi yang diperlukan saat menambahkan dukungan penyandian lainnya.

Berdasarkan penelitian, saya telah memperbarui cabang saya. Berikut adalah perbedaan antara linenoise head dan utf8-support branch . Seperti yang Anda lihat di sana, saya menyingkirkan semua kode khusus UTF-8 sepenuhnya dari linenoise.c dan memasukkannya ke dalam encodings/utf8.h dan encodings/utf8.c . Saya juga menambahkan satu API eksperimen yang disebut linenoiseSetEncodingFunctions di linenoise.h, sehingga pengguna dapat mengatur serangkaian fungsi penyandian mereka sendiri. Saya mengkonfirmasi semua fungsi masih berfungsi.

Berikut ini cuplikan API eksperimental saya saat ini:

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 dan linenoiseNextCharLen mengembalikan panjang byte sebagai nilai yang dikembalikan, dan mengatur panjang kolom ke parameter col_len . linenoiseReadCode membaca byte menjadi buf , dan mengonversi byte dan menetapkan kode karakter yang berarti untuk penyandian ke parameter c .

Jika pengguna tidak memanggil linenoiseSetEncodingFunctions , itu akan berakhir dengan memanggil implementasi _default_. Mereka hanya menangani _one byte_ sebagai karakter.

Semoga posting ini bermanfaat ketika Anda mendesain API pengkodean baru. Saya sangat menantikannya!!

@yhirose itu pekerjaan yang fantastis!!! :-) Saya akan memeriksa kode dan menggabungkannya. Terima kasih untuk ini.

Belum menyatu?

@antirez ada kemajuan dalam menggabungkannya?

Saya telah memodifikasi garpu saya (https://github.com/yhirose/linenoise/tree/utf8-support) untuk mengikuti perubahan terbaru yang dibuat pada linenoise asli seperti fitur 'petunjuk'.

Terima kasih banyak @yhirose. Anda telah membuat kode yang bagus menjadi lebih baik! dan saya
pekerjaan lebih mudah!

@sonophoto

Pada Senin, 27 Juni 2016 18:56:45 -0700, yhirose menulis:

   I have modified my fork 

(https://github.com/yhirose/linenoise/tree/utf8-support) untuk mengejar ketinggalan
dengan perubahan terbaru yang dibuat pada linenoise asli seperti 'petunjuk'
fitur.

Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub, atau matikan utasnya.

*

Garpu saya (https://github.com/yhirose/linenoise/tree/utf8-support) sekarang mendukung Unicode 9.0.

@antirez Apakah Anda memiliki waktu luang dalam waktu dekat untuk menggabungkan dukungan multi-byte https://github.com/hoelzro/lua-linenoise untuk menggunakan garpu @yhirose sampai saat itu? ️

Garpu saya (https://github.com/yhirose/linenoise/tree/utf8-support) sekarang mendukung Unicode 11.0 dan mencakup semua perubahan terbaru yang dibuat di antirez/linenoise .

Garpu saya (https://github.com/yhirose/linenoise/tree/utf8-support) sekarang mendukung Unicode 12.1.

Garpu saya (https://github.com/yhirose/linenoise/tree/utf8-support) sekarang mendukung Unicode 13.0.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

krux02 picture krux02  ·  8Komentar

JelteF picture JelteF  ·  8Komentar

ghost picture ghost  ·  4Komentar

denisvm picture denisvm  ·  9Komentar

fatcerberus picture fatcerberus  ·  5Komentar