Linenoise: إضافة دعم متعدد البايت

تم إنشاؤها على ٢٣ يناير ٢٠١٢  ·  21تعليقات  ·  مصدر: antirez/linenoise

لا يحتوي الكود الحالي على دعم للسلاسل متعددة البايت ، مثل السلاسل التي تحتوي على أحرف unicode تتجاوز نطاق ASCII. يتم حساب تحولات الأعمدة الخاصة بـ RefreshLine باستخدام strlen () الذي يُرجع 2 بدلاً من 1 لحرف 2 بايت مثل 'Ş' باللغة التركية.

يجب أن تستخدم المكتبة mbstowcs () أو وظائف أخرى للحصول على عدد الأحرف بدلاً من عدد البايتات لمعالجة العمود (الأسهم لأعلى ولأسفل ومحو حرف وما إلى ذلك).

وأيضًا نظرًا لأن هذه الوظائف تعتمد على LC_CTYPE ، يجب عليك أنت أو التطبيقات التي تستخدم linenoise استدعاء setlocale (LC_ALL، "") لتعيين لغة التطبيق إلى لغة النظام.

شكرا.

التعليق الأكثر فائدة

يدعم الآن My fork (https://github.com/yhirose/linenoise/tree/utf8-support) Unicode 11.0 ويتضمن جميع التغييرات الأخيرة التي تم إجراؤها في antirez / linenoise .

ال 21 كومينتر

ألق نظرة على مفترقتي ، https://github.com/msteveb/linenoise ، الذي يدعم UTF-8

هل تحتاج حقًا إلى كل هذه الوظائف؟ لست مألوفًا تمامًا مع الأشياء ولكني قمت بسهولة بإصلاح بعض المشكلات الغريبة باستخدام mbstowcs () بدلاً من strlen () حيث يُفترض أن طول السلسلة يعادل عدد الأحرف في السلسلة. لكن لم أجد طريقة لإصلاح حذف الأحرف العريضة بمسافة للخلف ..

النهج هنا هو تجنب أي اعتماد على دعم النظام لـ UTF-8. على سبيل المثال ، لدي أنظمة تقوم بتشغيل uClibc بدون دعم اللغة التي لا يزال بإمكانها تشغيل وحدة تحكم utf-8 عبر منفذ تسلسلي. بالطبع أنت مدعو لاتخاذ نهج مختلف.

عندى نفس المشكلة؛ لقد جربت ضجيج الخط لتطبيق shell. إذا كنت أرغب في مطالبات ملونة ، فسيتم تضمين أكواد الهروب في حساب الطول.

حل أبسط وأسهل هو eirther:

1) اسمح بتحديد طول الموجه بنفسك.
2) استخدم الأوامر الطرفية لاستخراج موضع المؤشر بعد إخراج الموجه (لست متأكدًا مما إذا كان ذلك ممكنًا)

أجد هذا من كود mongo shell. أنا دائمًا منزعج من المزيد والمزيد من أدوات CLI (mongo ، redis-cli ، عقدة)) أستخدم المؤشر الذي يتحرك بشكل غريب عندما تكون هناك أحرف متعددة البايت. لا أعرف ما إذا كان الآخرون يستخدمون linenoise أو أي شيء آخر ، لكني أرغب في إصلاح هذا الأمر :-)

لقد صنعت لينويزًا معدلًا يتيح لك تحديد العرض بنفسك ، لذا فهو عمل إضافي للتطبيق ، ولكن على الأقل ممكن ؛ لقد كنت أستخدمه منذ حوالي 3 أشهر دون أي مشاكل. ربما سأحوله إلى طلب سحب.

قام فرع 'utf-8 support' الموجود على مفترقتي بإصلاح مشكلات UTF-8 التالية التي تظهر في أحدث إصدار من linenoise 1.0:

  • أحرف متعددة البايت: ö (U+00F6)
  • الأحرف متعددة الأكواد: ö (U+006F U+0308)
  • الشخصيات العريضة: 日本語 ("اليابانية")
  • نص موجه بما في ذلك الأحرف أعلاه ونص ANSI هرب من النص الملون.

جربت أولاً https://github.com/msteveb/linenoise. لكنه لا يعتمد على أحدث خطوط لينينو التي تدعم الوضع متعدد الأسطر الرائع. كما أنه لا يدعم أحرف CJK العريضة والأحرف متعددة الأكواد ...

مرحبًا ، أفكر في السير في الطريق التالي مع هذه المشكلة:

  1. استخدم yhirose كمرجع للتحقق من المكان الذي يجب استبدال وظائف سلسلة C العادية بوظائف مدركة متعددة البايت.
  2. تصدير API الذي يسمح لمستخدم linenoise بتعيين وظائف بديلة لحسابات طول السلسلة. اضبط الوظيفة على وظائف C العادية كوظائف افتراضية.
  3. قم بتضمين كود yhirose كملف منفصل يمكنك إضافته إلى تطبيقك ، واستدعاء وظائف linenoise الجديدة لتعيين وظائف الطول ، من أجل الحصول على دعم متعدد البايت.

بهذه الطريقة نحصل على بساطة لينينو التي تظل دون تغيير تقريبًا ، ولكن اختياريًا ، من الممكن دعم كل من الأحرف متعددة البايت مع وظائف C++ ، أو قدم مستخدم آخر وظائف مختلفة عن الوظائف القياسية ، أو تلك المضمنة في Linenoise نفسه إذا المشروع في C ولا تريد إعادة كتابة ما كتبهyhirose بالفعل مرارًا وتكرارًا.

منطقي بالنسبة لك؟ شكرا.

antirez ، شكرًا على الاهتمام بمستخدمي الأكواد متعددة البايت! الفكرة التي قدمتها منطقية تمامًا بالنسبة لي. أنا أكثر سعادة لأنه إذا كانت مكتبة linenoise نفسها قادرة على توفير القابلية للتوسع ، فيمكننا بسهولة إضافة دعم ترميز متعدد البايت.

كما ترى في مفترقتي ، فإن أهم مفهوم لتمكين دعم "متعدد البايت" هو التمييز بوضوح بين " موضع / عرض البايت " في مخزن النص و " موضع / عرض العمود " على الشاشة. فيما يلي بعض الأمثلة في UTF-8:

  • (U + 3042): E3 81 82 (3 بايت): عريض (عرض عمودين)
  • ö (U + 00F6): C3 B6 (2 بايت): ضيق (عرض عمود واحد)
  • (U + 006F U + 0308): 6F CC 88 (3 بايت): ضيق (عرض عمود واحد)

بمجرد أن نعرف الفرق ، من السهل جدًا التعامل مع التعليمات البرمجية متعددة البايت بشكل صحيح. يمكنك فهم الفكرة من التغييرات في الالتزام الأول . لقد طبقت نفس المبدأ على النص الفوري في الالتزام الثاني أيضًا.

المكان الوحيد الذي نحتاج فيه إلى توخي الحذر هو رمز التعامل مع الوضع متعدد الأسطر. على سبيل المثال ، عندما يكون الحرف الأخير عريضًا ويوجد عمود واحد فقط في الصف الحالي ، فإن هذا الحرف العريض لا يتناسب مع المساحة المتبقية. لذلك يجب عرض الحرف العريض في بداية السطر التالي. هذا الرمز يعالجها.

شيء آخر قمت به هو تخطي جميع أحرف تسلسل هروب ANSI عند حساب موضع / عرض العمود في الالتزام الثالث . يتيح لنا هذا التغيير استخدام اللون في النص الفوري.

أنا متحمس حقًا لرؤية واجهة برمجة التطبيقات الجديدة في المستقبل القريب. يُرجى إعلامي إذا كان لديك أي أسئلة بخصوص هذا الموضوع. أنا متأكد من أنك ستقوم بعمل رائع !!

بعد البحث عن المزيد حول التبعيات بين كود Linenoise وكود ترميز UTF-8 وفقًا لهدف التصميم الخاص بك ، أدركت أن هناك حاجة إلى ثلاث وظائف فقط عند إضافة دعم ترميز آخر.

بناءً على البحث ، قمت بتحديث فرعي. هنا هو الفرق بين رأس Linenoise وفرع دعم utf8 . كما ترى هناك ، تخلصت تمامًا من جميع الأكواد المحددة لـ UTF-8 من linenoise.c ووضعتها في encodings/utf8.h و encodings/utf8.c . أضفت أيضًا واجهة برمجة تطبيقات تجربة واحدة تسمى linenoiseSetEncodingFunctions على linenoise.h ، حتى يتمكن المستخدمون من تعيين مجموعة وظائف الترميز الخاصة بهم. لقد أكدت أن جميع الوظائف لا تزال تعمل.

إليك مقتطف من واجهة برمجة التطبيقات التجريبية الحالية الخاصة بي:

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_ عمليات التنفيذ. إنهم يتعاملون ببساطة مع _one byte_ كحرف.

آمل أن يكون المنشور مفيدًا عند تصميم واجهة برمجة تطبيقات التشفير الجديدة. أتطلع إليها حقا!!

yhirose هذا عمل رائع !!! :-) سأقوم بفحص الكود ودمجها. شكرا لك على هذا.

لم يتم دمجها بعد؟

antirez أي تقدم في دمجها؟

لقد قمت بتعديل مفترقتي (https://github.com/yhirose/linenoise/tree/utf8-support) لمواكبة التغييرات الأخيرة التي تم إجراؤها في Linenoise الأصلي مثل ميزة "تلميحات".

شكرا جزيلاyhirose. لقد جعلت الشفرة الجيدة أفضل! و الخاص بي
عمل أسهل!

تضمين التغريدة

في الإثنين ، 27 حزيران (يونيو) 2016 18:56:45 -0700 ، كتب يهيروز:

   I have modified my fork 

(https://github.com/yhirose/linenoise/tree/utf8-support) للحاق بالركب
مع التغييرات الأخيرة التي تم إجراؤها على لينويز الأصلي مثل "تلميحات"
خاصية.
-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

*

يدعم الآن My fork (https://github.com/yhirose/linenoise/tree/utf8-support) Unicode 9.0.

antirez هل سيكون لديك وقت فراغ في المستقبل القريب لدمج دعمyhirose متعدد البايت؟ أم يجب علينا تبديل https://github.com/hoelzro/lua-linenoise لاستخدام مفترق yhirose حتى ذلك الحين؟ ✌️

يدعم الآن My fork (https://github.com/yhirose/linenoise/tree/utf8-support) Unicode 11.0 ويتضمن جميع التغييرات الأخيرة التي تم إجراؤها في antirez / linenoise .

يدعم الآن مفترقتي (https://github.com/yhirose/linenoise/tree/utf8-support) Unicode 12.1.

يدعم الآن مفترقتي (https://github.com/yhirose/linenoise/tree/utf8-support) Unicode 13.0.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

fatcerberus picture fatcerberus  ·  5تعليقات

denisvm picture denisvm  ·  9تعليقات

ghost picture ghost  ·  4تعليقات

JelteF picture JelteF  ·  8تعليقات

krux02 picture krux02  ·  8تعليقات