使用 GNU Readline; 如何在同一程序中添加 ncurses?
标题比我的实际目标更具体一些:
我有一个使用 GNU Readline 的命令行程序,主要用于命令历史记录(即使用向上箭头检索以前的命令)和其他一些细节。 现在,程序的输出似乎散布在用户的输入中,有时是可以的,但输出是异步的(它通过网络连接响应输入命令),有时会很烦人(例如,如果用户输入时输出行)正在输入新的内容)。
我想为这个程序添加一个功能:一个单独的输出“窗口”。 我考虑过使用 ncurses 来实现这一点。 但从 ncurses FAQ 看来,这两个库并不容易一起使用。
我可能会考虑使用 Editline 或 tecla 而不是 Readline,但我不清楚其中任何一个是否能解决我的问题。 我还会考虑使用 ncurses 以外的其他东西,包括提供两种功能(文本模式窗口和命令历史记录)的库,但我不知道什么是最好的。
哦,对彩色文本的支持可能会获得加分。 我怀疑我可以用 Readline 做到这一点,所以也许这是一个单独的问题,但如果我的问题的解决方案也可以轻松地为输出添加一些颜色,那就更好了。
我正在使用 Ubuntu Hardy (Linux 2.6)。
The title is a bit more specific than my actual goal:
I have a command-line program which uses GNU Readline, primarily for command history (i.e. retrieving previous commands using up-arrow) and some other niceties. Right now the program's output appears interspersed with the user's input, which sometimes is OK but the output is asynchronous (it comes via a network connection in response to the input commands), and that gets annoying sometimes (e.g. if lines are output when the user is typing new input).
I'd like to add a feature to this program: a separate "window" for the output. I thought about using ncurses for this. But it appears from the ncurses FAQ that the two libraries are not easy to use together.
I might consider using Editline or tecla instead of Readline, but it's not clear to me if either of those will solve my problem. I'd also consider using something other than ncurses, including a library which provides both kinds of functionality (text-mode windows and command history), but I don't know what might be best.
Oh, and support for colored text might get bonus points. I suspect I may be able to do that with Readline, so maybe it's a separate concern, but if a solution to my problem also makes it easy to add a bit of color to the output, so much the better.
I'm using Ubuntu Hardy (Linux 2.6).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我现在在 GitHub 上整理了一个简单的示例程序: https://github.com/ulfalizer/ readline-and-ncurses。
它支持无缝且高效的终端大小调整和多字节/组合/宽字符。 该代码有有用的注释。
截图如下:
I've now put together a simple example program on GitHub: https://github.com/ulfalizer/readline-and-ncurses.
It supports seamless and efficient terminal resizing and multibyte/combining/wide characters. The code has helpful comments.
Screenshot below:
我做了一些搜索,看来你运气不好。
对于 ncurses 替代品,有 SLang、Newt 和 Turbo
愿景。 俚语不仅仅是屏幕处理,因此更多
复杂,但也许它可以用于您的目的? 纽特使用屏幕
处理起来也简单很多,但是太简单而且是单线程模式
我认为是为了你的目的。
Turbo Vision 是 Borland 的文本模式图形库,由
他们所有的工具都是 80 年代末/90 年代初的。 Borland 发布了源码
当这类东西的市场减少时,就需要编写代码,并且有
现在是 Linux 的端口(旁注,这个项目似乎已经写了
它自己的涡轮视觉实现)。 该端口并没有死(有
今年有一些 cvs 更新,编译得很好(旧版本
没有)),但我发现的电视示例都不是最新的,我
在放弃其余部分之前,我只编译了其中的一些。
这有点遗憾,因为电视是一个很好的使用环境。
顺便说一句,电视是 C++ 的(我假设你正在使用 C?)。
对于 readline 的替代方案,有 libkinput,它可能有效
与 ncurses 一起(它说它可以使用 ncurses 的 terminfo。但我是
不确定这是否意味着它可以与 ncurses 用法共存)?
也许一种选择是在 ncurses 程序“外部”运行 readline
使用rlwrap?
I have done some searching, and it seems like you are out of luck.
For ncurses alternatives there are SLang, Newt and Turbo
Vision. Slang is much more than just screen handling and thus more
complex, but maybe it can be used for your purpose?. Newt uses the screen
handling and is much simpler, but too simple and single-threaded-mode
for your purpose I think.
Turbo vision is the text mode graphics library from Borland, used by
all their tools in the late 80s/early 90s. Borland released the source
code when the market for that kind of thing diminished, and there is
now a port for linux (side note, this project seems to have written
its own turbo vision implementation). That port is not dead (there have
been some cvs updates this year which compiled fine (the older releases
did not)), but none of the TV examples I found were up to date and I
did only got a few of them to compile before giving up on the rest.
This is a bit of a shame, because TV was a lovely environment to use.
TV is btw C++ (and I assume you are using C?).
For an alternative to readline, there is libkinput, which maybe works
together with ncurses (it says it can use ncurses' terminfo. but I am
not sure if that means that it can co-exists together with ncurses usage)?
Maybe one option is to run readline "externally" to your ncurses program
using rlwrap?
这让我敲了几个小时的头,所以只是为了避免人们在谷歌上搜索一些痛苦:
如果你使用 ncurses 的内置
SIGWINCH
处理程序和KEY_RESIZE
,请注意readline 默认设置 LINES 和 COLUMNS 环境变量。 这些会覆盖 ncurses 会执行的任何动态大小计算(通常使用ioctl()
TIOCGWINSZ
),这意味着即使在调整终端大小后,您也将继续获得初始终端大小。可以通过在初始化 readline 之前将 rl_change_environment 设置为 0 来防止这种情况。
更新:
以下是我从 readline 源中收集到的一些附加信息:
readline 的
SIGWINCH
处理代码(如果rl_catch_sigwinch
为 1,则使用该代码)确实会更新 < code>LINES 和COLUMNS
,这对于 ncurses 来说似乎应该足够了。 然而,当使用备用 readline 接口时(这在将 readline 与 ncurses 结合使用时最有意义),信号处理程序(包括用于 SIGWINCH 的信号处理程序)将仅在每个 rl_callback_read_char 的持续时间内安装() 调用,这意味着 readline 不会看到两次调用rl_callback_read_char()
之间的任何终端大小调整。This had me banging my head for a few hours, so just to save people Googling some pain:
If you're using ncurses' builtin
SIGWINCH
handler withKEY_RESIZE
, be aware that readline sets theLINES
andCOLUMNS
environment variables by default. These override any dynamic size calculation (usually withioctl()
TIOCGWINSZ
) that ncurses would otherwise do, meaning you'll keep getting the initial terminal size even after resizing the terminal.This can be prevented by setting
rl_change_environment
to0
before initializing readline.Update:
Here's some additional information I gleaned from the readline sources:
readline's
SIGWINCH
handling code (which is used ifrl_catch_sigwinch
is 1) does updateLINES
andCOLUMNS
, which seems like it should be sufficient for ncurses. However, when using the alternate readline interface (which makes most sense when combining readline with ncurses), the signal handlers (including the one forSIGWINCH
) will only be installed for the duration of eachrl_callback_read_char()
call, meaning any terminal resize between two calls torl_callback_read_char()
will not be seen by readline.原来gdb同时使用了readline和ncurses。 如果您有兴趣这样做,我建议您查看他们的实现: http://sourceware.org/git/?p=gdb.git;a=blob;f=gdb/tui/tui-io.c
So it turns out that gdb uses both readline and ncurses. If you're interested in doing this, I recommend that you check out their implementation: http://sourceware.org/git/?p=gdb.git;a=blob;f=gdb/tui/tui-io.c
我已经实现了您在我的程序中描述的内容:
http://dpc.ucore.info /lab:xmppconsole
以下是处理 io 的文件:
http://github.com/dpc/xmppconsole/blob/master/src/io.c
I've achieved what you've described in a program of mine:
http://dpc.ucore.info/lab:xmppconsole
The following is the file handling io:
http://github.com/dpc/xmppconsole/blob/master/src/io.c
我不确定你尝试的是哪个版本。 截至今天(2012.09.14),这非常简单,我们只需将自定义函数挂钩到以下函数指针即可。
我在这里做了一些合理的事情。
I'm not sure which version you tried. As of today(2012.09.14) It is very simple, We just need to hook our custom function to following function pointers.
I did something reasonable here.