假设我有一个ncurses程序,它在curses屏幕上做了一些工作,最后打印到stdout
。将此计划c.c
称为a.out
。
我希望cat $(./a.out)
首先启动ncurses,在执行某些操作后,a.out
退出并将c.c
打印到stdout
,cat
读取,{}因此打印文件c.c
的内容。
#include <stdio.h>
#include <ncurses.h>
int main() {
initscr();
noecho();
cbreak();
printw("hello world");
refresh();
getch();
endwin();
fprintf(stdout, "c.c");
return 0;
}
我还希望./a.out | xargs vim
,ls | ./a.out | xargs less
能够正常工作。
但是当我输入./a.out | xargs vim
时,hello world
永远不会出现。该命令似乎没有按顺序执行,vim没有打开c.c
。
使ncurses程序与其他linux工具一起使用的正确方法是什么?
答案 0 :(得分:2)
管道使用标准输出(stdout)和标准输入(stdin)。
最简单的方法 - 使用initscr
来初始化输出以使用标准输出,而不是使用newterm
,使用newterm(NULL, stderr, stdin);
,它允许您选择文件描述符,例如,
initscr();
而不是
newterm(NULL, stdout, stdin);
(几乎)与
相同<ncurses.h>
顺便说一下,当您加入<curses.h>
(或<stdio.h>
)时,无需包含f_open(&FileObject, filename_aux, FA_CREATE_ALWAYS | FA_WRITE);
do
{
/* Cache Maintenance */
SCB_CleanDCache_by_Addr((uint32_t *)buf, BUF_MAX_SIZE);
len = getAviableData(buf);
f_write(&FileObject, buf, len, (UINT*)&ByteWritten);
/* Data Memory Barrier */
__DMB();
total += ByteWritten;
}while(total < MAX_LEN)
f_close(&FileObject);
。
如果您想在管道的中间中使用您的程序,那就更复杂了:您必须耗尽标准输入并打开实际的终端设备。但这是另一个问题(已经得到回答)。
进一步阅读:
答案 1 :(得分:1)
ncurses
通过将一堆ansi转义写入stdout来工作,终端将解释它。您可以运行./a.out > file
,然后检查文件以查看您实际撰写的内容。它会立即显而易见,为什么程序会混淆:
$ cat -vE file
^[(B^[)0^[[?1049h^[[1;24r^[[m^O^[[4l^[[H^[[Jhello world^[[24;1H^[[?1049l^M^[[?1l^[>c.c
执行此操作的正确方法是在检测到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;
}
这是规范的Unix行为。
如果您不想强制显示用户界面,可以draw your UI on stderr。