diff --git a/example.c b/example.c index 3a7f8b37..beeb16b5 100644 --- a/example.c +++ b/example.c @@ -1,9 +1,14 @@ #include #include #include +#include +#include +#include #include #include "linenoise.h" +int resizePipe[2] = {-1, -1}; + void completion(const char *buf, linenoiseCompletions *lc) { if (buf[0] == 'h') { linenoiseAddCompletion(lc,"hello"); @@ -20,10 +25,26 @@ char *hints(const char *buf, int *color, int *bold) { return NULL; } +void handleResize(int sig) { + write(resizePipe[1], &sig, sizeof(sig)); +} + +int makeResizePipe(void) { + pipe(resizePipe); + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handleResize; + sigaction(SIGWINCH, &sa, NULL); + + return resizePipe[0]; +} + int main(int argc, char **argv) { char *line; char *prgname = argv[0]; int async = 0; + int async_resize = 0; /* Parse options, with --multiline we enable multi line editing. */ while(argc > 1) { @@ -37,8 +58,10 @@ int main(int argc, char **argv) { exit(0); } else if (!strcmp(*argv,"--async")) { async = 1; + } else if (!strcmp(*argv,"--async-resize")) { + async_resize = 1; } else { - fprintf(stderr, "Usage: %s [--multiline] [--keycodes] [--async]\n", prgname); + fprintf(stderr, "Usage: %s [--multiline] [--keycodes] [--async] [--async-resize]\n", prgname); exit(1); } } @@ -69,34 +92,47 @@ int main(int argc, char **argv) { * using the select(2) timeout. */ struct linenoiseState ls; char buf[1024]; + int resizefd = async_resize ? makeResizePipe() : -1; linenoiseEditStart(&ls,-1,-1,buf,sizeof(buf),"hello> "); while(1) { - fd_set readfds; - struct timeval tv; - int retval; - - FD_ZERO(&readfds); - FD_SET(ls.ifd, &readfds); - tv.tv_sec = 1; // 1 sec timeout - tv.tv_usec = 0; - - retval = select(ls.ifd+1, &readfds, NULL, NULL, &tv); - if (retval == -1) { - perror("select()"); - exit(1); - } else if (retval) { - line = linenoiseEditFeed(&ls); + fd_set readfds; + struct timeval tv; + int retval, maxfd; + + FD_ZERO(&readfds); + FD_SET(ls.ifd, &readfds); + tv.tv_sec = 1; // 1 sec timeout + tv.tv_usec = 0; + maxfd = ls.ifd; + + if (resizefd > 0) { + FD_SET(resizefd, &readfds); + if (resizefd > maxfd) maxfd = resizefd; + } + + retval = select(maxfd+1, &readfds, NULL, NULL, &tv); + if (retval == -1) { + if (errno != EINTR) { + perror("select()"); + exit(1); + } + } else if (FD_ISSET(ls.ifd, &readfds)) { + line = linenoiseEditFeed(&ls); /* A NULL return means: line editing is continuing. * Otherwise the user hit enter or stopped editing * (CTRL+C/D). */ if (line != linenoiseEditMore) break; - } else { - // Timeout occurred + } else if (FD_ISSET(resizefd, &readfds)) { + int ignore; + read(resizefd, &ignore, sizeof(ignore)); + linenoiseResize(&ls); + } else { + // Timeout occurred static int counter = 0; linenoiseHide(&ls); - printf("Async output %d.\n", counter++); + printf("Async output %d.\n", counter++); linenoiseShow(&ls); - } + } } linenoiseEditStop(&ls); if (line == NULL) exit(0); /* Ctrl+D/C. */ diff --git a/linenoise.c b/linenoise.c index db9b06cb..47fd0d93 100644 --- a/linenoise.c +++ b/linenoise.c @@ -1093,6 +1093,11 @@ void linenoiseShow(struct linenoiseState *l) { } } +/* In async mode, call this after terminal size has changed. */ +void linenoiseResize(struct linenoiseState *l) { + l->cols = getColumns(l->ifd, l->ofd); +} + /* Insert the character(s) 'c' of length 'clen' at cursor current position. * This handles both single-byte ASCII and multi-byte UTF-8 sequences. * diff --git a/linenoise.h b/linenoise.h index e56b6271..c29f85f7 100644 --- a/linenoise.h +++ b/linenoise.h @@ -80,6 +80,7 @@ char *linenoiseEditFeed(struct linenoiseState *l); void linenoiseEditStop(struct linenoiseState *l); void linenoiseHide(struct linenoiseState *l); void linenoiseShow(struct linenoiseState *l); +void linenoiseResize(struct linenoiseState *l); /* Blocking API. */ char *linenoise(const char *prompt);