I want to write a app like sgtpep/pmenu in C.
Then I start to look at the ncurses
library. My first try is able to select the menu. Such as when I do ls | ./a.out
, it should be able to show all the files, and highlight the first one, when I press UP or DOWN, it will change highlight different item accordingly.
The full code is here.
The program does not receive any keypresses. mvprintw(n+1, 0, "%d\n", ch);
inside the loop always print -1
.
Then I remove the unrelated code, and get the minimal example.
#include <stdio.h>
char buf[100];
int main(int argc, char **argv) {
int ch;
while (fgets(buf, sizeof(buf), stdin)) puts(buf);
ch = getch();
printf("%d\n", ch);
ch = getch();
printf("%d\n", ch);
ch = getch();
printf("%d\n", ch);
ch = getch();
printf("%d\n", ch);
return 0;
}
ch
is always -1
. I suspect the stdin
is not clean, so I use fflush(stdin)
after fgets
, but it results the same.
So what is the correct way to read from stdin
?
UPD1
#include <stdio.h>
char buf[100];
int main(int argc, char **argv) {
int ch;
while (fgets(buf, sizeof(buf), stdin)) puts(buf);
fflush(stdin);
ch = getchar();
printf("%d\n", ch);
ch = getchar();
printf("%d\n", ch);
ch = getchar();
printf("%d\n", ch);
ch = getchar();
printf("%d\n", ch);
return 0;
}
I have modified the program, so it is not related to ncurses
anymore, but when running ls | ./a.out
, ch
keeps showing -1
.
UPD2
Use newterm
to redirect in
and out
works.
FILE *fd = fopen("/dev/tty", "r+");
set_term(newterm(NULL, fd, fd)); // instead of initscr()
noecho();
cbreak();
keypad(stdscr, TRUE);
print_menu(cur, n);
while (true) {
ch = getch();
if (ch == KEY_UP || ch == 'k') --cur;
else if (ch == KEY_DOWN || ch == 'j') ++cur;
cur = (cur + n) % n;
print_menu(cur, n);
}
endwin();
If you're going to switch from stdin to curses in that way, you'll have to open the terminal device, e.g., /dev/tty
when you're done reading the standard input. Once you've opened the terminal, you can initialize curses using newterm
(which has parameters for the input/output streams unlike initscr
).
For examples, see the ncurses test-program, or dialog.