Reputation: 176
I would like to be able to call an ncurses based program via command substitution so its output can be passed as a command line argument to the another program. For example, this is easy to do in bash when the program does not go into curses mode:
echo $(pwd) # should be the same as just calling pwd alone
When I try to do this with my program (whose code follows below), curses mode is never entered, and the string "test" is never printed. It is important to enter curses mode because this is where, theoretically, the user would somehow manipulate the string that is finally printed to stdout (right now that string is just static).
echo $(./a.out) # just prints an empty line
My program will return the string "this is not a test" when run normally after curses mode is entered, "test" is printed to the screen, and the user presses a key.
./a.out # normal run
Here is the offending code:
// test.cpp
#include <ncurses.h>
#include <iostream>
using namespace std;
/* get curses up and running */
void init() {
initscr(); // start curses mode, might clear screen
raw(); // disable line buff, and C-z/C-c won't gen sigals; see cbreak()
keypad(stdscr, TRUE); // enable arrow keys and function keys
noecho(); // don't echo chars user types
}
/* shut curses down */
void end() {
endwin(); // end curses mode
}
int main()
{
init();
printw("test");
getch();
end();
cout << "this is not a test" << endl;
return 0;
}
I compile with this command:
g++ test.cpp -lcurses
Thank you for your help!
Upvotes: 1
Views: 2207
Reputation: 241721
Here's a simple solution, using newterm
:
#define _XOPEN_SOURCE
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
// start curses mode
SCREEN* s = NULL;
FILE* out = stdout;
if(!isatty(fileno(stdout))) {
out = fopen("/dev/tty", "w");
// Should really test `out` to make sure that worked.
setbuf(out, NULL);
}
// Here, we don't worry about the case where stdin has been
// redirected, but we could do something similar to out
// for input, opening "/dev/tty" in mode "r" for in if necessary.
s = newterm(NULL, out, stdin);
printw("test");
getch();
endwin(); // end curses mode
delscreen(s);
puts("/home/matt");
return 0;
}
Upvotes: 2