[英]how to make ncurses program working with other linux utils?
Suppose I have a ncurses program which does some job on curses screen, and finally print something to stdout
. 假设我有一个ncurses程序,该程序在curses屏幕上完成一些工作,最后将一些内容打印到
stdout
。 Call this program cc
, compiled to a.out
. 将此程序
cc
编译为a.out
。
I expect cat $(./a.out)
first fire up ncurses, after some action, a.out
quits and print cc
to stdout
, which is read by cat
, and thus print content of file cc
. 我希望
cat $(./a.out)
首先启动ncurses,在执行某些操作后, a.out
退出并将cc
打印到stdout
,该目录由cat
读取,从而打印文件cc
内容。
#include <stdio.h>
#include <ncurses.h>
int main() {
initscr();
noecho();
cbreak();
printw("hello world");
refresh();
getch();
endwin();
fprintf(stdout, "c.c");
return 0;
}
I also expect ./a.out | xargs vim
我也希望
./a.out | xargs vim
./a.out | xargs vim
, ls | ./a.out | xargs less
./a.out | xargs vim
ls | ./a.out | xargs less
ls | ./a.out | xargs less
ls | ./a.out | xargs less
to work. ls | ./a.out | xargs less
工作。
But when I type ./a.out | xargs vim
但是当我输入
./a.out | xargs vim
./a.out | xargs vim
, hello world
never shows up. ./a.out | xargs vim
, hello world
永远不会出现。 The command seems not executed in order, vim does not open cc
. 该命令似乎未按顺序执行,vim无法打开
cc
。
What is the correct way to make a ncurses program to work with other linux utils? 使ncurses程序与其他linux utils配合使用的正确方法是什么?
Pipes use the standard output (stdout) and standard input (stdin). 管道使用标准输出(stdout)和标准输入(stdin)。
The simplest way - rather than using initscr
, which initializes the output to use the standard output , use newterm
, which allows you to choose the file descriptors, eg, 最简单的方法-使用
initscr
,而不是使用initscr
初始化输出以使用标准输出 ,而是使用newterm
,它允许您选择文件描述符,例如,
newterm(NULL, stderr, stdin);
rather than 而不是
initscr();
which is (almost) the same as (几乎)与
newterm(NULL, stdout, stdin);
By the way, when you include <ncurses.h>
(or <curses.h>
), there is no need to include <stdio.h>
. 顺便说一句,当您包含
<ncurses.h>
(或<curses.h>
)时,无需包含<stdio.h>
。
If you wanted to use your program in the middle of a pipe, that is more complicated: you would have to drain the standard input and open the actual terminal device. 如果要在管道中间使用程序,那将更加复杂:您必须排空标准输入并打开实际的终端设备。 But that's another question (and has already been answered).
但这是另一个问题(并且已经得到回答)。
Further reading: 进一步阅读:
ncurses
works by writing a bunch of ansi escapes to stdout, which the terminal will interpret. ncurses
通过将一堆ansi转义写入stdout来工作,终端将对其进行解释。 You can run ./a.out > file
and then inspect the file to see what you're actually writing. 您可以运行
./a.out > file
,然后检查该文件以查看实际编写的内容。 It'll be immediately obvious why programs are confused: 显而易见为什么程序会被混淆:
$ cat -vE file
^[(B^[)0^[[?1049h^[[1;24r^[[m^O^[[4l^[[H^[[Jhello world^[[24;1H^[[?1049l^M^[[?1l^[>c.c
The correct way of doing this is to skip all the graphical/textual UI parts when you detect that stdout is not a terminal, ie it's consumed by a program instead of a user: 正确的方法是在检测到stdout不是终端时跳过所有图形/文本UI部分,即它是由程序而不是用户使用的:
#include <unistd.h>
#include <stdio.h>
#include <ncurses.h>
int main() {
if(isatty(1)) {
// Output is a terminal. Show stuff to the user.
initscr();
noecho();
cbreak();
printw("hello world");
refresh();
getch();
endwin();
} else {
// Output is consumed by a program.
// Skip UI.
}
fprintf(stdout, "c.c");
return 0;
}
This is the canonical Unix behavior. 这是标准的Unix行为。
If you instead want to force your UI to be shown regardless, you can draw your UI on stderr . 如果您想无论如何都强制显示UI,则可以在stderr上绘制UI 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.