forked from test34/can_wizard
Multiplexing: make completion non-blocking as well.
from orig commit a1d8e18
This commit is contained in:
parent
3a76d34b7b
commit
d8c9e6fdfe
2 changed files with 50 additions and 46 deletions
|
@ -265,57 +265,57 @@ static void freeCompletions(linenoiseCompletions *lc) {
|
||||||
* the input was consumed by the completeLine() function to navigate the
|
* the input was consumed by the completeLine() function to navigate the
|
||||||
* possible completions, and the caller should read for the next characters
|
* possible completions, and the caller should read for the next characters
|
||||||
* from stdin. */
|
* from stdin. */
|
||||||
static int completeLine(struct linenoiseState *ls) {
|
static int completeLine(struct linenoiseState *ls, int keypressed) {
|
||||||
linenoiseCompletions lc = { 0, NULL };
|
linenoiseCompletions lc = { 0, NULL };
|
||||||
int nread, nwritten;
|
int nwritten;
|
||||||
char c = 0;
|
char c = keypressed;
|
||||||
|
|
||||||
completionCallback(ls->buf,&lc);
|
completionCallback(ls->buf,&lc);
|
||||||
if (lc.len == 0) {
|
if (lc.len == 0) {
|
||||||
linenoiseBeep();
|
linenoiseBeep();
|
||||||
|
ls->in_completion = 0;
|
||||||
} else {
|
} else {
|
||||||
size_t stop = 0, i = 0;
|
|
||||||
|
|
||||||
while(!stop) {
|
switch(c) {
|
||||||
/* Show completion or original buffer */
|
case 9: /* tab */
|
||||||
if (i < lc.len) {
|
if (ls->in_completion == 0) {
|
||||||
struct linenoiseState saved = *ls;
|
ls->in_completion = 1;
|
||||||
|
ls->completion_idx = 0;
|
||||||
|
} else {
|
||||||
|
ls->completion_idx = (ls->completion_idx+1) % (lc.len+1);
|
||||||
|
if (ls->completion_idx == lc.len) linenoiseBeep();
|
||||||
|
}
|
||||||
|
c = 0;
|
||||||
|
break;
|
||||||
|
case 27: /* escape */
|
||||||
|
/* Re-show original buffer */
|
||||||
|
if (ls->completion_idx < lc.len) refreshLine(ls);
|
||||||
|
ls->in_completion = 0;
|
||||||
|
c = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Update buffer and return */
|
||||||
|
if (ls->completion_idx < lc.len) {
|
||||||
|
nwritten = snprintf(ls->buf,ls->buflen,"%s",
|
||||||
|
lc.cvec[ls->completion_idx]);
|
||||||
|
ls->len = ls->pos = nwritten;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
ls->in_completion = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ls->len = ls->pos = strlen(lc.cvec[i]);
|
/* Show completion or original buffer */
|
||||||
ls->buf = lc.cvec[i];
|
if (ls->in_completion && ls->completion_idx < lc.len) {
|
||||||
refreshLine(ls);
|
struct linenoiseState saved = *ls;
|
||||||
ls->len = saved.len;
|
ls->len = ls->pos = strlen(lc.cvec[ls->completion_idx]);
|
||||||
ls->pos = saved.pos;
|
ls->buf = lc.cvec[ls->completion_idx];
|
||||||
ls->buf = saved.buf;
|
refreshLine(ls);
|
||||||
} else {
|
ls->len = saved.len;
|
||||||
refreshLine(ls);
|
ls->pos = saved.pos;
|
||||||
}
|
ls->buf = saved.buf;
|
||||||
|
} else {
|
||||||
nread = fread(&c, 1, 1, stdin);
|
refreshLine(ls);
|
||||||
if (nread <= 0) {
|
|
||||||
freeCompletions(&lc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(c) {
|
|
||||||
case TAB: /* tab */
|
|
||||||
i = (i+1) % (lc.len+1);
|
|
||||||
if (i == lc.len) linenoiseBeep();
|
|
||||||
break;
|
|
||||||
case ESC: /* escape */
|
|
||||||
/* Re-show original buffer */
|
|
||||||
if (i < lc.len) refreshLine(ls);
|
|
||||||
stop = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Update buffer and return */
|
|
||||||
if (i < lc.len) {
|
|
||||||
nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]);
|
|
||||||
ls->len = ls->pos = nwritten;
|
|
||||||
}
|
|
||||||
stop = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,6 +741,7 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
|
||||||
int linenoiseEditStart(struct linenoiseState *l, char *buf, size_t buflen, const char *prompt) {
|
int linenoiseEditStart(struct linenoiseState *l, char *buf, size_t buflen, const char *prompt) {
|
||||||
/* Populate the linenoise state that we pass to functions implementing
|
/* Populate the linenoise state that we pass to functions implementing
|
||||||
* specific editing functionalities. */
|
* specific editing functionalities. */
|
||||||
|
l->in_completion = 0;
|
||||||
l->buf = buf;
|
l->buf = buf;
|
||||||
l->buflen = buflen;
|
l->buflen = buflen;
|
||||||
l->prompt = prompt;
|
l->prompt = prompt;
|
||||||
|
@ -799,8 +800,8 @@ char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
/* Only autocomplete when the callback is set. It returns < 0 when
|
/* Only autocomplete when the callback is set. It returns < 0 when
|
||||||
* there was an error reading from fd. Otherwise it will return the
|
* there was an error reading from fd. Otherwise it will return the
|
||||||
* character that should be handled next. */
|
* character that should be handled next. */
|
||||||
if (c == 9 && completionCallback != NULL) {
|
if ((l->in_completion || c == 9) && completionCallback != NULL) {
|
||||||
c = completeLine(l);
|
c = completeLine(l,c);
|
||||||
/* Return on errors */
|
/* Return on errors */
|
||||||
if (c < 0) return NULL;
|
if (c < 0) return NULL;
|
||||||
/* Read next character when 0 */
|
/* Read next character when 0 */
|
||||||
|
|
|
@ -52,6 +52,9 @@ extern char *linenoiseEditMore;
|
||||||
* We pass this state to functions implementing specific editing
|
* We pass this state to functions implementing specific editing
|
||||||
* functionalities. */
|
* functionalities. */
|
||||||
struct linenoiseState {
|
struct linenoiseState {
|
||||||
|
int in_completion; /* The user pressed TAB and we are now in completion
|
||||||
|
* mode, so input is handled by completeLine(). */
|
||||||
|
size_t completion_idx; /* Index of next completion to propose. */
|
||||||
char *buf; /* Edited line buffer. */
|
char *buf; /* Edited line buffer. */
|
||||||
size_t buflen; /* Edited line buffer size. */
|
size_t buflen; /* Edited line buffer size. */
|
||||||
const char *prompt; /* Prompt to display. */
|
const char *prompt; /* Prompt to display. */
|
||||||
|
|
Loading…
Reference in a new issue