Skip to content

Commit

Permalink
linenoise: update to latest version
Browse files Browse the repository at this point in the history
  • Loading branch information
bapt committed Feb 11, 2025
1 parent b9110bd commit 0af5fe5
Showing 1 changed file with 44 additions and 18 deletions.
62 changes: 44 additions & 18 deletions external/linenoise/linenoise.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ struct current {
stringbuf *output; /* used only during refreshLine() - output accumulator */
#if defined(USE_TERMIOS)
int fd; /* Terminal fd */
int pending; /* pending char fd_read_char() */
#elif defined(USE_WINCONSOLE)
HANDLE outh; /* Console output handle */
HANDLE inh; /* Console input handle */
Expand Down Expand Up @@ -426,8 +427,11 @@ static int enableRawMode(struct current *current) {
* We want read to return every single byte, without timeout. */
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */

/* put terminal in raw mode after flushing */
if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) {
/* put terminal in raw mode. Because we aren't changing any output
* settings we don't need to use TCSADRAIN and I have seen that hang on
* OpenBSD when running under a pty
*/
if (tcsetattr(current->fd,TCSANOW,&raw) < 0) {
goto fatal;
}
rawmode = 1;
Expand All @@ -436,14 +440,14 @@ static int enableRawMode(struct current *current) {

static void disableRawMode(struct current *current) {
/* Don't even check the return value as it's too late. */
if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1)
if (rawmode && tcsetattr(current->fd,TCSANOW,&orig_termios) != -1)
rawmode = 0;
}

/* At exit we'll try to fix the terminal to the initial conditions. */
static void linenoiseAtExit(void) {
if (rawmode) {
tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios);
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
}
linenoiseHistoryFree();
}
Expand Down Expand Up @@ -535,25 +539,31 @@ void linenoiseClearScreen(void)
}

/**
* Reads a char from 'fd', waiting at most 'timeout' milliseconds.
* Reads a char from 'current->fd', waiting at most 'timeout' milliseconds.
*
* A timeout of -1 means to wait forever.
*
* Returns -1 if no char is received within the time or an error occurs.
*/
static int fd_read_char(int fd, int timeout)
static int fd_read_char(struct current *current, int timeout)
{
struct pollfd p;
unsigned char c;

p.fd = fd;
if (current->pending) {
c = current->pending;
current->pending = 0;
return c;
}

p.fd = current->fd;
p.events = POLLIN;

if (poll(&p, 1, timeout) == 0) {
/* timeout */
return -1;
}
if (read(fd, &c, 1) != 1) {
if (read(current->fd, &c, 1) != 1) {
return -1;
}
return c;
Expand All @@ -571,7 +581,11 @@ static int fd_read(struct current *current)
int i;
int c;

if (read(current->fd, &buf[0], 1) != 1) {
if (current->pending) {
buf[0] = current->pending;
current->pending = 0;
}
else if (read(current->fd, &buf[0], 1) != 1) {
return -1;
}
n = utf8_charlen(buf[0]);
Expand All @@ -587,7 +601,7 @@ static int fd_read(struct current *current)
utf8_tounicode(buf, &c);
return c;
#else
return fd_read_char(current->fd, -1);
return fd_read_char(current, -1);
#endif
}

Expand All @@ -600,6 +614,15 @@ static int queryCursor(struct current *current, int* cols)
{
struct esc_parser parser;
int ch;
/* Unfortunately we don't have any persistent state, so assume
* a process will only ever interact with one terminal at a time.
*/
static int query_cursor_failed;

if (query_cursor_failed) {
/* If it ever fails, don't try again */
return 0;
}

/* Should not be buffering this output, it needs to go immediately */
assert(current->output == NULL);
Expand All @@ -609,7 +632,7 @@ static int queryCursor(struct current *current, int* cols)

/* Parse the response: ESC [ rows ; cols R */
initParseEscapeSeq(&parser, 'R');
while ((ch = fd_read_char(current->fd, 100)) > 0) {
while ((ch = fd_read_char(current, 100)) > 0) {
switch (parseEscapeSequence(&parser, ch)) {
default:
continue;
Expand All @@ -620,11 +643,14 @@ static int queryCursor(struct current *current, int* cols)
}
break;
case EP_ERROR:
/* Push back the character that caused the error */
current->pending = ch;
break;
}
/* failed */
break;
}
query_cursor_failed = 1;
return 0;
}

Expand Down Expand Up @@ -691,9 +717,9 @@ static int getWindowSize(struct current *current)
* If no additional char is received within a short time,
* CHAR_ESCAPE is returned.
*/
static int check_special(int fd)
static int check_special(struct current *current)
{
int c = fd_read_char(fd, 50);
int c = fd_read_char(current, 50);
int c2;

if (c < 0) {
Expand All @@ -704,7 +730,7 @@ static int check_special(int fd)
return meta(c);
}

c2 = fd_read_char(fd, 50);
c2 = fd_read_char(current, 50);
if (c2 < 0) {
return c2;
}
Expand All @@ -727,7 +753,7 @@ static int check_special(int fd)
}
if (c == '[' && c2 >= '1' && c2 <= '8') {
/* extended escape */
c = fd_read_char(fd, 50);
c = fd_read_char(current, 50);
if (c == '~') {
switch (c2) {
case '2':
Expand All @@ -746,7 +772,7 @@ static int check_special(int fd)
}
while (c != -1 && c != '~') {
/* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */
c = fd_read_char(fd, 50);
c = fd_read_char(current, 50);
}
}

Expand Down Expand Up @@ -1539,7 +1565,7 @@ static int reverseIncrementalSearch(struct current *current)
}
#ifdef USE_TERMIOS
if (c == CHAR_ESCAPE) {
c = check_special(current->fd);
c = check_special(current);
}
#endif
if (c == ctrl('R')) {
Expand Down Expand Up @@ -1651,7 +1677,7 @@ static int linenoiseEdit(struct current *current) {

#ifdef USE_TERMIOS
if (c == CHAR_ESCAPE) { /* escape sequence */
c = check_special(current->fd);
c = check_special(current);
}
#endif
if (c == -1) {
Expand Down

0 comments on commit 0af5fe5

Please sign in to comment.