linenoise: actively flush the output stream, in case it is buffered

This commit is contained in:
Ivan Grokhotkov
2020-04-30 16:51:02 +02:00
parent 440574d13b
commit f54d771cd3

View File

@@ -203,6 +203,13 @@ void linenoiseSetDumbMode(int set) {
dumbmode = set; dumbmode = set;
} }
static void flushWrite(void) {
if (__fbufsize(stdout) > 0) {
fflush(stdout);
}
fsync(fileno(stdout));
}
/* Use the ESC [6n escape sequence to query the horizontal cursor position /* Use the ESC [6n escape sequence to query the horizontal cursor position
* and return it. On error -1 is returned, on success the position of the * and return it. On error -1 is returned, on success the position of the
* cursor. */ * cursor. */
@@ -213,7 +220,7 @@ static int getCursorPosition(void) {
/* Report cursor location */ /* Report cursor location */
fprintf(stdout, "\x1b[6n"); fprintf(stdout, "\x1b[6n");
flushWrite();
/* Read the response: ESC [ rows ; cols R */ /* Read the response: ESC [ rows ; cols R */
while (i < sizeof(buf)-1) { while (i < sizeof(buf)-1) {
if (fread(buf+i, 1, 1, stdin) != 1) break; if (fread(buf+i, 1, 1, stdin) != 1) break;
@@ -238,6 +245,7 @@ static int getColumns(void) {
/* Go to right margin and get position. */ /* Go to right margin and get position. */
if (fwrite("\x1b[999C", 1, 6, stdout) != 6) goto failed; if (fwrite("\x1b[999C", 1, 6, stdout) != 6) goto failed;
flushWrite();
cols = getCursorPosition(); cols = getCursorPosition();
if (cols == -1) goto failed; if (cols == -1) goto failed;
@@ -248,6 +256,7 @@ static int getColumns(void) {
if (fwrite(seq, 1, strlen(seq), stdout) == -1) { if (fwrite(seq, 1, strlen(seq), stdout) == -1) {
/* Can't recover... */ /* Can't recover... */
} }
flushWrite();
} }
return cols; return cols;
@@ -258,12 +267,14 @@ failed:
/* Clear the screen. Used to handle ctrl+l */ /* Clear the screen. Used to handle ctrl+l */
void linenoiseClearScreen(void) { void linenoiseClearScreen(void) {
fprintf(stdout,"\x1b[H\x1b[2J"); fprintf(stdout,"\x1b[H\x1b[2J");
flushWrite();
} }
/* Beep, used for completion when there is nothing to complete or when all /* Beep, used for completion when there is nothing to complete or when all
* the choices were already shown. */ * the choices were already shown. */
static void linenoiseBeep(void) { static void linenoiseBeep(void) {
fprintf(stdout, "\x7"); fprintf(stdout, "\x7");
flushWrite();
} }
/* ============================== Completion ================================ */ /* ============================== Completion ================================ */
@@ -468,6 +479,7 @@ static void refreshSingleLine(struct linenoiseState *l) {
snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen)); snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
abAppend(&ab,seq,strlen(seq)); abAppend(&ab,seq,strlen(seq));
if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */ if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */
flushWrite();
abFree(&ab); abFree(&ab);
} }
@@ -555,6 +567,7 @@ static void refreshMultiLine(struct linenoiseState *l) {
l->oldpos = l->pos; l->oldpos = l->pos;
if (fwrite(ab.b,ab.len,1,stdout) == -1) {} /* Can't recover from write error. */ if (fwrite(ab.b,ab.len,1,stdout) == -1) {} /* Can't recover from write error. */
flushWrite();
abFree(&ab); abFree(&ab);
} }
@@ -581,6 +594,7 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
/* Avoid a full update of the line in the /* Avoid a full update of the line in the
* trivial case. */ * trivial case. */
if (fwrite(&c,1,1,stdout) == -1) return -1; if (fwrite(&c,1,1,stdout) == -1) return -1;
flushWrite();
} else { } else {
refreshLine(l); refreshLine(l);
} }
@@ -726,6 +740,7 @@ static int linenoiseEdit(char *buf, size_t buflen, const char *prompt)
int pos1 = getCursorPosition(); int pos1 = getCursorPosition();
if (fwrite(prompt,l.plen,1,stdout) == -1) return -1; if (fwrite(prompt,l.plen,1,stdout) == -1) return -1;
flushWrite();
int pos2 = getCursorPosition(); int pos2 = getCursorPosition();
if (pos1 >= 0 && pos2 >= 0) { if (pos1 >= 0 && pos2 >= 0) {
l.plen = pos2 - pos1; l.plen = pos2 - pos1;
@@ -881,9 +896,7 @@ static int linenoiseEdit(char *buf, size_t buflen, const char *prompt)
linenoiseEditDeletePrevWord(&l); linenoiseEditDeletePrevWord(&l);
break; break;
} }
if (__fbufsize(stdout) > 0) { flushWrite();
fflush(stdout);
}
} }
return l.len; return l.len;
} }
@@ -894,14 +907,16 @@ void linenoiseAllowEmpty(bool val) {
int linenoiseProbe(void) { int linenoiseProbe(void) {
/* Switch to non-blocking mode */ /* Switch to non-blocking mode */
int flags = fcntl(STDIN_FILENO, F_GETFL); int stdin_fileno = fileno(stdin);
int flags = fcntl(stdin_fileno, F_GETFL);
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
int res = fcntl(STDIN_FILENO, F_SETFL, flags); int res = fcntl(stdin_fileno, F_SETFL, flags);
if (res != 0) { if (res != 0) {
return -1; return -1;
} }
/* Device status request */ /* Device status request */
fprintf(stdout, "\x1b[5n"); fprintf(stdout, "\x1b[5n");
flushWrite();
/* Try to read response */ /* Try to read response */
int timeout_ms = 200; int timeout_ms = 200;
@@ -915,7 +930,7 @@ int linenoiseProbe(void) {
} }
/* Restore old mode */ /* Restore old mode */
flags &= ~O_NONBLOCK; flags &= ~O_NONBLOCK;
res = fcntl(STDIN_FILENO, F_SETFL, flags); res = fcntl(stdin_fileno, F_SETFL, flags);
if (res != 0) { if (res != 0) {
return -1; return -1;
} }
@@ -935,6 +950,7 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
count = linenoiseEdit(buf, buflen, prompt); count = linenoiseEdit(buf, buflen, prompt);
fputc('\n', stdout); fputc('\n', stdout);
flushWrite();
return count; return count;
} }
@@ -961,6 +977,7 @@ static int linenoiseDumb(char* buf, size_t buflen, const char* prompt) {
fputc(c, stdout); /* echo */ fputc(c, stdout); /* echo */
} }
fputc('\n', stdout); fputc('\n', stdout);
flushWrite();
return count; return count;
} }