简体   繁体   English

如何使ncurses程序与其他linux utils一起使用?

[英]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 vimhello 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.

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