diff --git a/linenoise.c b/linenoise.c index db9b06cb..724089a4 100644 --- a/linenoise.c +++ b/linenoise.c @@ -447,7 +447,7 @@ static int utf8SingleCharWidth(const char *s, size_t len) { } enum KEY_ACTION{ - KEY_NULL = 0, /* NULL */ + KEY_NULL = 0, /* NULL */ CTRL_A = 1, /* Ctrl+a */ CTRL_B = 2, /* Ctrl-b */ CTRL_C = 3, /* Ctrl-c */ @@ -736,11 +736,10 @@ static int completeLine(struct linenoiseState *ls, int keypressed) { } c = 0; break; - case 27: /* escape */ - /* Re-show original buffer */ + case 27: /* escape or escape sequence */ + /* Re-show original buffer, i.e. exit completion loop */ if (ls->completion_idx < lc.len) refreshLine(ls); ls->in_completion = 0; - c = 0; break; default: /* Update buffer and return */ @@ -1319,7 +1318,7 @@ char *linenoiseEditFeed(struct linenoiseState *l) { * count limits. */ if (!isatty(l->ifd) && !getenv("LINENOISE_ASSUME_TTY")) return linenoiseNoTTY(); - char c; + char c, pc; int nread; char seq[3]; @@ -1340,6 +1339,9 @@ char *linenoiseEditFeed(struct linenoiseState *l) { c = retval; } +pending: + pc = 0; + switch(c) { case ENTER: /* enter */ history_len--; @@ -1399,11 +1401,22 @@ char *linenoiseEditFeed(struct linenoiseState *l) { case CTRL_N: /* ctrl-n */ linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); break; - case ESC: /* escape sequence */ - /* Read the next two bytes representing the escape sequence. + case ESC: /* escape or escape sequence */ + /* We cannot distinguish an ESC key press from other keys + * presses that generate escape sequences. + * This could be the start of an escape sequence or the user + * might have pressed the ESC just to leave the completion loop, + * in the last case care must be taken to avoid consuming input. + * Read the next two bytes representing the escape sequence. * Use two calls to handle slow terminals returning the two * chars at different times. */ if (read(l->ifd,seq,1) == -1) break; + if (seq[0] != '[' && seq[0] != 'O') { + /* Not a known sequence. Assume ESC was already used (e.g. + * by completeLine) and set the pending char to reparse. */ + pc = seq[0]; + break; + } if (read(l->ifd,seq+1,1) == -1) break; /* ESC [ sequences. */ @@ -1496,6 +1509,10 @@ char *linenoiseEditFeed(struct linenoiseState *l) { linenoiseEditDeletePrevWord(l); break; } + if (pc) { + c = pc; + goto pending; + } return linenoiseEditMore; }