彩色 readline 提示符会中断 control-a

Colorized readline prompt breaks control-a

以下程序打印彩色的 readline 提示。它破坏了 control-a(光标最终比它应该的更靠右):

#include <readline/readline.h>
#include <readline/history.h>

#define CYELLOW "[=10=]1\e[0;31m[=10=]2"
#define RESET   "[=10=]1\e[0m[=10=]2"

int main(int argc, char **argv)
{
    readline(CYELLOW "prompt> " RESET);
    return 0;
}

当我在没有彩色提示的情况下调用 readline() 时,control-a 起作用:

readline("prompt> ");

我正在使用 Mac OS X 10.9.4。这是 otool 的输出:

/usr/lib/libreadline.dylib:
    /usr/lib/libedit.3.dylib (compatibility version 2.0.0, current version 3.0.0)
    /usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1

有几个 Whosebug 问题似乎涉及到这个问题:

他们都提到颜色标记需要用\001和\002括起来。我按照这些说明进行操作,但 control-a 仍然损坏。

Mac OS X 使用 NetBSD editline 库,其中包括 readline.

的部分兼容性实现

似乎已尝试添加 readline 的功能,允许用户在提示中使用字符 RL_PROMPT_START_IGNORERL_PROMPT_END_IGNORE(定义为 '''' 分别在 readline.h 中)。不幸的是,由于一个小错字,该功能从未在 rl_initialize.

中启用

当我阅读代码时(我还没有测试过),修复方法是更改​​ readline.c 的第 327 行 [见注释 1] 来自:

el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);

至:

el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);

这需要您找到 libedit 的源代码,进行微不足道的更改,重新配置并重新编译,然后安装。我没有 Mac,所以无法指导您完成该过程。 (请参阅注释 1 以获取可能有用的源存储库链接。)

另一个解决方案是在您的项目中使用 GNU readline 库。它显然在 MacPorts 中可用,因此如果您使用它,安装起来应该很容易。


备注:

  1. 我从这个 OS X source repository. In the head revision of the NetBSD distribution 得到了那个行号,它在第 337 行。但是通过搜索 EL_PROMPT 应该很容易找到它。只要确保符号 EL_PROMPT_ESC 定义在 histedit.h 中即可;如果不是,则您找到的 editline 库的版本可能太旧了。