简体   繁体   English

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

[英]Using GNU Readline; how can I add ncurses in the same program?

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 (ie retrieving previous commands using up-arrow) and some other niceties. 我有一个使用GNU Readline的命令行程序,主要用于命令历史记录(即使用向上箭头检索以前的命令)和其他一些细节。 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 (eg 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. 我考虑过为此使用ncurses。 But it appears from the ncurses FAQ that the two libraries are not easy to use together. 但是从ncurses常见问题解答看来,这两个库很难一起使用。

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. 我可能会考虑使用Editlinetecla而不是Readline,但是我不清楚这两种方法是否都能解决我的问题。 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. 我还考虑使用ncurses以外的其他工具,包括提供两种功能(文本模式窗口和命令历史记录)的库,但我不知道哪种方法最好。

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. 我怀疑我可以使用Readline做到这一点,所以也许这是一个单独的问题,但是如果解决我的问题也可以轻松为输出添加一些颜色,那就更好了。

I'm using Ubuntu Hardy (Linux 2.6). 我正在使用Ubuntu Hardy(Linux 2.6)。

I've now put together a simple example program on GitHub: https://github.com/ulfalizer/readline-and-ncurses . 我现在在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和readline的程序的屏幕截图

I have done some searching, and it seems like you are out of luck. 我做了一些搜索,看来您不走运。

For ncurses alternatives there are SLang , Newt and Turbo Vision . 对于ncurses替代品,有SLangNewtTurbo Vision Slang is much more than just screen handling and thus more complex, but maybe it can be used for your purpose?. lang语不仅限于屏幕处理,因此更为复杂,但也许可以将其用于您的目的? Newt uses the screen handling and is much simpler, but too simple and single-threaded-mode for your purpose I think. Newt使用屏幕处理功能,它要简单得多,但我认为它太简单了,并且单线程模式对您而言没有意义。

Turbo vision is the text mode graphics library from Borland, used by all their tools in the late 80s/early 90s. Turbo vision是Borland的文本模式图形库,在80年代末90年代初被其所有工具使用。 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). 当此类产品的市场减少时,Borland会发布源代码,并且现在有一个linux端口(注意, 该项目似乎已经编写了自己的turbo vision实现)。 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. 这个端口还没有死(今年有一些cvs更新可以编译好(旧版本没有)),但是我发现的电视示例都没有最新,在此之前我只编译了其中的几个放弃其余的。 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?). 电视是C ++(我假设您正在使用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)? 对于readline的替代方法,有libkinput ,它可能与ncurses一起使用(它说它可以使用ncurses的terminfo。但是我不确定这是否意味着它可以与ncurses用法共存)?

Maybe one option is to run readline "externally" to your ncurses program using rlwrap ? 也许一种选择是使用rlwrap在您的ncurses程序“外部”运行readline?

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 with KEY_RESIZE , be aware that readline sets the LINES and COLUMNS environment variables by default. 如果将ncurses的内置SIGWINCH处理程序与KEY_RESIZE一起KEY_RESIZE ,请注意,默认情况下,readline会设置LINESCOLUMNS环境变量。 These override any dynamic size calculation (usually with ioctl() TIOCGWINSZ ) that ncurses would otherwise do, meaning you'll keep getting the initial terminal size even after resizing the terminal. 它们会覆盖ncurses否则会执行的任何动态大小计算(通常使用ioctl() TIOCGWINSZ ),这意味着即使在调整终端大小之后,您仍将保持初始终端大小。

This can be prevented by setting rl_change_environment to 0 before initializing readline. 可以在初始化rl_change_environment行之前将rl_change_environment设置为0来防止此情况。

Update: 更新:

Here's some additional information I gleaned from the readline sources: 这是我从readline来源收集到的一些其他信息:

readline's SIGWINCH handling code (which is used if rl_catch_sigwinch is 1) does update LINES and COLUMNS , which seems like it should be sufficient for ncurses. readline的SIGWINCH处理代码(如果rl_catch_sigwinch为1时使用)会更新LINESCOLUMNS ,这似乎对ncurses足够了。 However, when using the alternate readline interface (which makes most sense when combining readline with ncurses), the signal handlers (including the one for SIGWINCH ) will only be installed for the duration of each rl_callback_read_char() call, meaning any terminal resize between two calls to rl_callback_read_char() will not be seen by readline. 但是,当使用备用readline接口(将readline与ncurses结合使用时最有意义)时,信号处理程序(包括SIGWINCH的信号处理程序)将仅在每次rl_callback_read_char()调用期间安装,这意味着任何终端在两个之间调整大小readline不会看到对rl_callback_read_char()调用。

So it turns out that gdb uses both readline and ncurses. 因此,事实证明gdb同时使用了readline和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 : //sourceware.org/git/?p=gdb.git;a=blob;f=gdb/tui/tui-io.c

I've achieved what you've described in a program of mine: 我已经实现了您在我的程序中描述的内容:

http://dpc.ucore.info/lab:xmppconsole http://dpc.ucore.info/lab:xmppconsole

The following is the file handling io: 以下是io文件处理:

http://github.com/dpc/xmppconsole/blob/master/src/io.c http://github.com/dpc/xmppconsole/blob/master/src/io.c

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. 截至今天(2012.09.14),这非常简单,我们只需要将自定义函数挂接到以下函数指针即可。

rl_getch_function
rl_redisplay_function
rl_completion_display_matches_hook

I did something reasonable here . 我在这里做了一些合理的事情

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM