如何让ncurses程序与其他linux工具一起使用?

时间:2017-04-07 17:12:08

标签: c pipe ncurses curses

假设我有一个ncurses程序,它在curses屏幕上做了一些工作,最后打印到stdout。将此计划c.c称为a.out

我希望cat $(./a.out)首先启动ncurses,在执行某些操作后,a.out退出并将c.c打印到stdoutcat读取,{}因此打印文件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 vimls | ./a.out | xargs less能够正常工作。

但是当我输入./a.out | xargs vim时,hello world永远不会出现。该命令似乎没有按顺序执行,vim没有打开c.c

使ncurses程序与其他linux工具一起使用的正确方法是什么?

2 个答案:

答案 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