当前代码不支持多字节字符串,例如具有超出 ASCII 范围的 unicode 字符的字符串。 refreshLine 的列偏移是使用 strlen() 计算的,对于土耳其语中的 'Ş' 等 2 字节字符,它返回 2 而不是 1。
库应该使用 mbstowcs() 或其他函数来获取字符数而不是用于列处理的字节数(向上、向下箭头、擦除字符等)。
而且由于这些函数依赖于 LC_CTYPE,您或使用 linenoise 的应用程序都应该调用 setlocale(LC_ALL, "") 将应用程序的语言环境设置为系统语言环境。
谢谢。
请参阅: 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)
日本語
('日语')我首先尝试了https://github.com/msteveb/linenoise。 但它不是基于支持梦幻般的多行模式的最新 linenoise。 它也不支持 CJK 宽字符和多码字符...
您好,我正在考虑使用以下方法解决此问题:
通过这种方式,我们获得了 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.h
和encodings/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);
linenoisePrevCharLen
和linenoiseNextCharLen
返回字节长度作为返回值,并将列长度设置为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。
最有用的评论
我的 fork (https://github.com/yhirose/linenoise/tree/utf8-support) 现在支持 Unicode 11.0 并包括antirez/linenoise 中最近所做的所有更改。