Skip to content

Commit a1d8e18

Browse files
committed
Multiplexing: make completion non-blocking as well.
1 parent 65db823 commit a1d8e18

File tree

2 files changed

+49
-45
lines changed

2 files changed

+49
-45
lines changed

linenoise.c

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -355,57 +355,57 @@ static void freeCompletions(linenoiseCompletions *lc) {
355355
* the input was consumed by the completeLine() function to navigate the
356356
* possible completions, and the caller should read for the next characters
357357
* from stdin. */
358-
static int completeLine(struct linenoiseState *ls) {
358+
static int completeLine(struct linenoiseState *ls, int keypressed) {
359359
linenoiseCompletions lc = { 0, NULL };
360-
int nread, nwritten;
361-
char c = 0;
360+
int nwritten;
361+
char c = keypressed;
362362

363363
completionCallback(ls->buf,&lc);
364364
if (lc.len == 0) {
365365
linenoiseBeep();
366+
ls->in_completion = 0;
366367
} else {
367-
size_t stop = 0, i = 0;
368-
369-
while(!stop) {
370-
/* Show completion or original buffer */
371-
if (i < lc.len) {
372-
struct linenoiseState saved = *ls;
373-
374-
ls->len = ls->pos = strlen(lc.cvec[i]);
375-
ls->buf = lc.cvec[i];
376-
refreshLine(ls);
377-
ls->len = saved.len;
378-
ls->pos = saved.pos;
379-
ls->buf = saved.buf;
380-
} else {
381-
refreshLine(ls);
382-
}
368+
switch(c) {
369+
case 9: /* tab */
370+
if (ls->in_completion == 0) {
371+
ls->in_completion = 1;
372+
ls->completion_idx = 0;
373+
} else {
374+
ls->completion_idx = (ls->completion_idx+1) % (lc.len+1);
375+
if (ls->completion_idx == lc.len) linenoiseBeep();
376+
}
377+
c = 0;
378+
break;
379+
case 27: /* escape */
380+
/* Re-show original buffer */
381+
if (ls->completion_idx < lc.len) refreshLine(ls);
382+
ls->in_completion = 0;
383+
c = 0;
384+
break;
385+
default:
386+
/* Update buffer and return */
387+
if (ls->completion_idx < lc.len) {
388+
nwritten = snprintf(ls->buf,ls->buflen,"%s",
389+
lc.cvec[ls->completion_idx]);
390+
ls->len = ls->pos = nwritten;
391+
c = 0;
392+
}
393+
ls->in_completion = 0;
394+
break;
395+
}
383396

384-
nread = read(ls->ifd,&c,1);
385-
if (nread <= 0) {
386-
freeCompletions(&lc);
387-
return -1;
388-
}
397+
/* Show completion or original buffer */
398+
if (ls->in_completion && ls->completion_idx < lc.len) {
399+
struct linenoiseState saved = *ls;
389400

390-
switch(c) {
391-
case 9: /* tab */
392-
i = (i+1) % (lc.len+1);
393-
if (i == lc.len) linenoiseBeep();
394-
break;
395-
case 27: /* escape */
396-
/* Re-show original buffer */
397-
if (i < lc.len) refreshLine(ls);
398-
stop = 1;
399-
break;
400-
default:
401-
/* Update buffer and return */
402-
if (i < lc.len) {
403-
nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]);
404-
ls->len = ls->pos = nwritten;
405-
}
406-
stop = 1;
407-
break;
408-
}
401+
ls->len = ls->pos = strlen(lc.cvec[ls->completion_idx]);
402+
ls->buf = lc.cvec[ls->completion_idx];
403+
refreshLine(ls);
404+
ls->len = saved.len;
405+
ls->pos = saved.pos;
406+
ls->buf = saved.buf;
407+
} else {
408+
refreshLine(ls);
409409
}
410410
}
411411

@@ -841,6 +841,7 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
841841
int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) {
842842
/* Populate the linenoise state that we pass to functions implementing
843843
* specific editing functionalities. */
844+
l->in_completion = 0;
844845
l->ifd = stdin_fd != -1 ? stdin_fd : STDIN_FILENO;
845846
l->ofd = stdout_fd != -1 ? stdout_fd : STDOUT_FILENO;
846847
l->buf = buf;
@@ -908,8 +909,8 @@ char *linenoiseEditFeed(struct linenoiseState *l) {
908909
/* Only autocomplete when the callback is set. It returns < 0 when
909910
* there was an error reading from fd. Otherwise it will return the
910911
* character that should be handled next. */
911-
if (c == 9 && completionCallback != NULL) {
912-
c = completeLine(l);
912+
if ((l->in_completion || c == 9) && completionCallback != NULL) {
913+
c = completeLine(l,c);
913914
/* Return on errors */
914915
if (c < 0) return NULL;
915916
/* Read next character when 0 */

linenoise.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ extern char *linenoiseEditMore;
5151
* We pass this state to functions implementing specific editing
5252
* functionalities. */
5353
struct linenoiseState {
54+
int in_completion; /* The user pressed TAB and we are now in completion
55+
* mode, so input is handled by completeLine(). */
56+
size_t completion_idx; /* Index of next completion to propose. */
5457
int ifd; /* Terminal stdin file descriptor. */
5558
int ofd; /* Terminal stdout file descriptor. */
5659
char *buf; /* Edited line buffer. */

0 commit comments

Comments
 (0)