彩色的readline提示打破了控制-a

时间:2015-07-09 23:19:20

标签: c macos readline

以下程序打印彩色的readline提示。它打破了控制-a(光标最终向右移动得比它应该的更远):

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

#define CYELLOW "\001\e[0;31m\002"
#define RESET   "\001\e[0m\002"

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

有几个stackoverflow问题似乎与此有关:

他们都提到颜色标记需要被\ 001和\ 002括起来。我遵循了这些指示但控制权仍然被打破了。

1 个答案:

答案 0 :(得分:6)

Mac OS X使用NetBSD editline库,其中包含readline的部分兼容性实现。

似乎尝试添加readline的功能,允许用户使用字符RL_PROMPT_START_IGNORERL_PROMPT_END_IGNORE(定义为'\1'和{'\2'来提示提示中的终端控制序列。分别在readline.h){1}}。遗憾的是,由于拼写错误,该功能永远不会在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获得了这个行号。在head revision of the NetBSD distribution中,它位于337行。但是通过搜索EL_PROMPT来查找它应该很容易。只需确保EL_PROMPT_ESC中定义了符号histedit.h;如果不是,您发现的编辑行库的版本可能太旧了。