terminfoメモ
node.jsでwrapする前にc++でterminfo, termios, readlineの使いかたを練習。
// g++ -o cursor cursor.cpp -lcurses -lreadline #include <stdlib.h> #include <term.h> #include <curses.h> #include <errno.h> #include <readline/readline.h> class Termios { struct termios save_term; struct termios temp_term; void update() { errno = 0; if(tcsetattr(fileno(stdin), TCSANOW, &temp_term) == -1){ perror("tcsetattr failure"); exit(EXIT_FAILURE); } } public: Termios() { // save term errno = 0; if(tcgetattr(fileno(stdin), &save_term) == -1){ perror("tcgetattr failure"); exit(EXIT_FAILURE); } temp_term=save_term; } ~Termios() { restore(); } void no_canonical() { temp_term.c_iflag &= IGNCR; temp_term.c_oflag &= ONLRET; temp_term.c_lflag &= (~ISIG & ~ICANON & ~ECHO); temp_term.c_cc[VMIN] = 1; temp_term.c_cc[VTIME] = 5; update(); } void restore() { tcsetattr(fileno(stdin), TCSANOW, &save_term); temp_term=save_term; } void echo(bool enable) { if(enable){ temp_term.c_lflag |= ECHO; } else{ temp_term.c_lflag &= ~ECHO; } update(); } }; class Terminfo { public: static void initialize() { if(setupterm(NULL, fileno(stdout), (int *)0) == ERR){ fprintf(stderr,"setupterm failure\n"); exit(EXIT_FAILURE); } cmd("clear"); } static void cmd(const char *cmd) { errno=0; char *parmcmd=tparm(tigetstr(cmd)); if(parmcmd==NULL){ perror("tparm NULL"); exit(EXIT_FAILURE); } tputs(parmcmd, 1, putchar); } }; Termios termios; int main(int argc, char **argv) { termios.no_canonical(); Terminfo::initialize(); bool loop=true; while(loop){ switch(getchar()) { default: break; case 'q': loop=false; break; case 'h': Terminfo::cmd("cub1"); break; case 'j': Terminfo::cmd("cud1"); break; case 'k': Terminfo::cmd("cuu1"); break; case 'l': Terminfo::cmd("cuf1"); break; case ' ': termios.echo(true); readline("input:"); termios.echo(false); break; } } return 0; }
node.jsのncursesを見てみたが、terminfoの関数(tputs, tigetstr, tparmあたり)はエクスポートしていないみたいなので自作することにした。ついでにreadlineも混ぜておいた。