使用GNU Readline,我如何在同一个程序中添加ncurses?

25

标题比我的实际目标更加具体:

我有一个命令行程序,它使用GNU Readline,主要用于命令历史记录(即使用上箭头检索以前的命令)和其他一些美好功能。当前,程序的输出与用户的输入交织在一起,有时可以接受,但输出是异步的(它通过网络连接响应输入命令),有时会很烦人(例如,如果在用户键入新输入时输出行)。

我想给这个程序添加一个功能:单独的输出"窗口"。我考虑使用 ncurses 来完成这个功能。但从 ncurses FAQ 看来,两个库不容易一起使用。

我可能会考虑使用 Editlinetecla 代替 Readline,但我不确定它们是否能解决我的问题。我也会考虑使用除了 ncurses 以外的其他东西,包括提供两种功能(文本模式窗口和命令历史记录)的库,但我不知道什么最好。

哦,对了,对于彩色文本的支持可能会得到额外的奖励。我怀疑我可以用 Readline 做到这一点,所以也许这是一个单独的问题,但如果解决我的问题也使添加一些颜色到输出变得容易,那就更好了。

我正在使用 Ubuntu Hardy(Linux 2.6)。


我放弃了(并坚持使用 readline)。 - John Zwinck
6个回答

18

太棒了!这个代码许可证是什么?如果可能的话,我想将它与一些MIT许可的材料集成。谢谢! - cxw
很高兴能帮到你!如果这样最方便的话,我可以将它放在MIT下。否则,我会选择ISC,而MIT看起来相似。顺便说一句,我还有一个版本是通过select()循环(或在这种情况下使用epoll())运行的,位于https://github.com/ulfalizer/botniklas。我被分心了,还没有推送它,但如果您感兴趣,我可以为它创建一个分支。 - Ulfalizer
该版本安装了一个SIGWINCH处理程序(使用signalfd()而不是普通处理程序),并允许readline直接从stdin读取。这也恰好修复了搜索和多字节字符的问题。 - Ulfalizer
这很棒,但在OS X El CapitanTerminal上不支持滚动功能。相反,它会滚动readline的历史记录。也许与此有关:http://www.macissues.com/2014/06/10/yosemite-introduces-per-line-scrolling-in-the-terminal/ - Adam
@Adam:没有滚动功能。顶部窗口仅添加为了获得更有趣的布局,并实际上通过示例中的readline输入执行某些操作。 - Ulfalizer

6

我做了一些搜索,看起来你运气不太好。

对于ncurses的替代方案,有SLangNewtTurbo Vision。SLang不仅仅是屏幕处理,更加复杂,但也许可以用于你的目的?Newt使用屏幕处理,更加简单,但对于你的目的来说可能过于简单和单线程模式。

Turbo Vision是Borland的文本模式图形库,在80年代末/90年代初使用于他们所有的工具中。当这种类型的市场减少时,Borland发布了源代码,并且现在有一个适用于Linux的端口(顺便说一句,这个项目似乎编写了自己的Turbo Vision实现)。这个端口并没有死亡(今年已经有一些cvs更新,编译得很好(旧版本则没有),但我发现找到的TV示例都不是最新的,只有其中的一部分编译成功,剩下的我放弃了。这有点可惜,因为TV是一个可爱的环境。顺便说一下,TV是C++(我猜你在使用C?)。

对于readline的替代方案,有libkinput,也许可以与ncurses一起使用(它说它可以使用ncurses的terminfo,但我不确定这是否意味着它可以与ncurses的使用共存)?

也许一个选项是在你的ncurses程序中“外部”运行readline,使用rlwrap


俚语本身就是一种语言。此外,它只适用于GPL2许可证的最新版本。我原以为它是一个库。 - matiu
请注意,Newt是在SLang之上的一层。它可能更容易使用,但它只是另一个选项。 - Alexis Wilke

5
这让我苦思冥想了几个小时,为了避免人们搜索痛苦,如果您正在使用ncurses内置的SIGWINCH处理程序与KEY_RESIZE,请注意readline默认设置LINES和COLUMNS环境变量。这将覆盖任何动态大小计算(通常使用ioctl() TIOCGWINSZ),否则ncurses会执行,这意味着即使调整终端大小,您仍将获得初始终端大小。
可以通过在初始化readline之前将rl_change_environment设置为0来防止这种情况发生。
更新:
以下是我从readline源代码中获取的一些额外信息:
readline的SIGWINCH处理代码(如果rl_catch_sigwinch为1,则使用)确实更新LINES和COLUMNS,这似乎应该足以满足ncurses的要求。然而,当使用备用readline接口(与ncurses结合使用时最有意义)时,信号处理程序(包括SIGNAL WINCH的处理程序)仅在每个rl_callback_read_char()调用的持续时间安装,这意味着在两个调用rl_callback_read_char()之间进行的任何终端调整大小都不会被readline看到。

1
请考虑格式化您的答案。命令/代码很难阅读。 - ryanyuyu

4

哇,谢谢你。欢迎来到StackOverflow,Guillaume。 :) - John Zwinck

3

2

我不确定你尝试的是哪个版本。截至今天(2012.09.14),很简单,我们只需要将自定义函数挂钩到以下函数指针即可。

rl_getch_function
rl_redisplay_function
rl_completion_display_matches_hook

我在这里做了一些合理的事情(链接)


1
好的,我找到了。首先要显示 rl_display_prompt,然后是 rl_line_buffer,最后将光标偏移量设置为 rl_point + strlen(rl_display_prompt) - nccc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接