Linenoise: 添加多字节支持

创建于 2012-01-23  ·  21评论  ·  资料来源: antirez/linenoise

当前代码不支持多字节字符串,例如具有超出 ASCII 范围的 unicode 字符的字符串。 refreshLine 的列偏移是使用 strlen() 计算的,对于土耳其语中的 'Ş' 等 2 字节字符,它返回 2 而不是 1。

库应该使用 mbstowcs() 或其他函数来获取字符数而不是用于列处理的字节数(向上、向下箭头、擦除字符等)。

而且由于这些函数依赖于 LC_CTYPE,您或使用 linenoise 的应用程序都应该调用 setlocale(LC_ALL, "") 将应用程序的语言环境设置为系统语言环境。

谢谢。

最有用的评论

我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 现在支持 Unicode 11.0 并包括antirez/linenoise 中最近所做的所有更改。

所有21条评论

请参阅: http :

看看我的 fork, https://github.com/msteveb/linenoise ,它支持 utf-8

你真的需要所有这些功能吗? 我不太熟悉这些东西,但我通过使用 mbstowcs() 而不是 strlen() 轻松解决了一些奇怪的问题,其中假设字符串的长度等于字符串中的字符数。 但是我找不到用退格键修复删除宽字符的方法..

这里的方法是避免对系统支持 utf-8 的任何依赖。 例如,我有运行 uClibc 的系统而没有语言环境支持,它仍然可以通过串行端口愉快地运行 utf-8 控制台。 当然,欢迎您采取不同的方法。

我有个类似的问题; 我为 shell 实现尝试了 line-noise。 如果我想要彩色提示,转义码最终会包含在长度计算中。

一个更简单、更容易的解决方法是:

1) 允许自己指定提示的长度。
2)输出提示后使用终端命令提取光标位置(不确定是否可行)

我从 mongo shell 的代码中找到了这个。 我总是对我使用的越来越多的 CLI 工具(mongo、redis-cli、node)感到恼火,当有多字节字符时,它们的光标移动异常。 我不知道其他人是否在使用 linenoise 或其他东西,但我希望看到这个问题得到解决:-)

我做了一个修改过的 linenoise,让你自己指定宽度,所以它对应用程序来说是额外的工作,但至少是可能的; 我已经使用它大约 3 个月了,没有任何问题。 也许我会把它变成一个拉取请求。

我的 fork 上的“utf-8 support”分支修复了最新 linenoise 1.0 版中出现的以下 UTF-8 问题:

  • 多字节字符: ö (U+00F6)
  • 多码字符: ö (U+006F U+0308)
  • 宽字符: 日本語 ('日语')
  • 包含上述字符和 ANSI 转义彩色文本的提示文本。

我首先尝试了https://github.com/msteveb/linenoise。 但它不是基于支持梦幻般的多行模式的最新 linenoise。 它也不支持 CJK 宽字符和多码字符...

您好,我正在考虑使用以下方法解决此问题:

  1. 使用@yhirose作为参考,以检查 C 纯字符串函数应在何处替换为多字节感知函数。
  2. 导出允许 linenoise 用户为字符串长度计算设置替代函数的 API。 将函数设置为默认的普通 C 函数。
  3. @yhirose代码作为一个单独的文件包含在您的应用程序中,您可以调用 linenoise 新函数来设置长度函数,以获得多字节支持。

通过这种方式,我们获得了 linenoise 的简单性几乎保持不变,但可以选择支持多字节字符,包括C++函数,其他用户提供的不同于标准函数的函数,或者 linenoise 本身包含的函数,如果你项目是用 C 语言编写的,您不想一次又一次地重写@yhirose已经写过的内容。

对你有意义吗? 谢谢。

@antirez ,感谢关注多字节代码用户! 你提出的想法对我来说完全有意义。 我更高兴,因为如果 linenoise 库本身可以提供可扩展性,我们可以轻松添加其他多字节编码支持。

正如您在我的 fork 中看到的,启用“多字节”支持的最重要概念是明确区分文本缓冲区中的“字节位置/宽度”和屏幕上的“列位置/宽度”。 以下是 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 列时,该宽字符不适合剩余空间。 所以宽字符必须显示在下一行的开头。 这段代码处理它。

我做的另一件事是在计算第三次提交

我真的很高兴在不久的将来看到新的 API。 如果您对此事有任何疑问,请告诉我。 我相信你会做得非常出色!!

根据您的设计目标研究了 linenoise 代码和 UTF-8 编码代码之间的依赖关系后,我意识到在添加其他编码支持时只需要三个函数。

根据研究,我更新了我的分支。 这是linenoise head 和 utf8-support 分支之间的差异。 正如您在那里看到的那样,我完全从linenoise.c删除了所有 UTF-8 特定代码,并将它们放入encodings/utf8.hencodings/utf8.c 。 此外,我在 linenoise.h 上添加了一个名为linenoiseSetEncodingFunctions实验 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);

linenoisePrevCharLenlinenoiseNextCharLen返回字节长度作为返回值,并将列长度设置为col_len参数。 linenoiseReadCode字节读入buf ,并将字节转换并为编码设置有意义的字符代码到c参数。

如果用户不调用linenoiseSetEncodingFunctions ,它最终会调用 _default_ 实现。 他们只是将_一个字节_作为一个字符处理。

希望这篇文章能在您设计新的编码 API 时有所帮助。 我真的很期待呢!!

@yhirose ,这是一项了不起的工作!!! :-) 我要检查代码并合并它。 这次真是万分感谢。

还没合并?

@antirez在合并方面有什么进展吗?

我已经修改了我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 以赶上最近在原始 linenoise 中所做的更改,例如“提示”功能。

非常感谢@yhirose。 你已经把好的代码做得更好了! 和我的
工作更轻松!

@sonophoto

在 2016 年 6 月 27 日星期一 18:56:45 -0700,yhirose 写道:

   I have modified my fork 

(https://github.com/yhirose/linenoise/tree/utf8-support) 赶上
随着最近对原始 linenoise 的更改,例如“提示”
特征。

您收到此消息是因为您订阅了此线程。
直接回复此邮件,在 GitHub 上查看,或将线程静音。

*

我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 现在支持 Unicode 9.0。

@antirez在不久的将来您是否有空闲时间来合并@yhirose的多字节支持? 或者我们应该在此之前切换https://github.com/hoelzro/lua-linenoise以使用@yhirose的叉子吗? ✌️

我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 现在支持 Unicode 11.0 并包括antirez/linenoise 中最近所做的所有更改。

我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 现在支持 Unicode 12.1。

我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 现在支持 Unicode 13.0。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

fatcerberus picture fatcerberus  ·  5评论

krux02 picture krux02  ·  8评论

denisvm picture denisvm  ·  9评论

JelteF picture JelteF  ·  8评论

ghost picture ghost  ·  4评论