diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-06-03 07:00:45 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-06-03 07:00:45 -0700 |
commit | 75c23fb66297c7fcd3eba0d485a7bb4f0116ad47 (patch) | |
tree | 2b5315d11091764c382b9a28cf03e6c08a8f6ecf | |
parent | 28256ba13885ac924d90dd0b0e639165af7ec373 (diff) | |
download | txr-75c23fb66297c7fcd3eba0d485a7bb4f0116ad47.tar.gz txr-75c23fb66297c7fcd3eba0d485a7bb4f0116ad47.tar.bz2 txr-75c23fb66297c7fcd3eba0d485a7bb4f0116ad47.zip |
listener: deodorize EOF handling.
This is motivated by seeing a poor behavior, whose
manifestation is platform dependent. In the listener if
we run, say (get-json) and hit Ctrl-D, then after
the get-json function reports failure, the listener
will quit as if it received EOF. On older glibc/Linux
systems, the listener does not experience EOF.
Furthermore, in the EOF situation, this misleading diagnostic
is seen: ** error reading interactive input.
* parser.c (repl): Call clear_error on in_stream just before
calling linenoise. This gets rid of any sticky EOF condition
left behind by an input operation. On POSIX systems, if you
use stdin to read from a terminal and receive EOF, you must
clearerr(stdin) before continuing to read from the terminal.
Otherwise input operations on the stream can just return the
cached error indication without attempting to perform any
input on the file descriptor. Somehow we are getting away
without doing this on older systems like Ubuntu 18. Maybe
something changed in the glibc stdio implementation.
* linenoise/linenoise.c (complete_line): Don't directly
return -1 on EOF, just set the stop = 1 variable, so the
WEOF value will be returned, similarly to how it is done
in history_search.
(history_search): Set the error variable on EOF.
(edit): Set the error variable on EOF.
-rw-r--r-- | linenoise/linenoise.c | 8 | ||||
-rw-r--r-- | parser.c | 2 |
2 files changed, 6 insertions, 4 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index b905d444..15d919b8 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -635,10 +635,8 @@ static int complete_line(lino_t *ls, int substring) { free_completions(&lc); lino_os.free_fn(lt); ls->error = (lino_os.eof_fn(ls->tty_ifs) ? lino_eof : lino_ioerr); - return -1; - } - - switch (c) { + stop = 1; + } else switch (c) { case TAB: i = (i+1) % (lc.len+1); if (i == lc.len) generate_beep(ls); @@ -751,6 +749,7 @@ static int history_search(lino_t *l) handle_resize(lc, l); continue; } + lc->error = (lino_os.eof_fn(lc->tty_ifs) ? lino_eof : lino_ioerr); stop = 1; } else { if (vb) @@ -2120,6 +2119,7 @@ static int edit(lino_t *l, const wchar_t *prompt) if (c == WEOF) { ret = l->len ? l->len : -1; + l->error = (lino_os.eof_fn(l->tty_ifs) ? lino_eof : lino_ioerr); goto out; } @@ -1769,6 +1769,8 @@ val repl(val bindings, val in_stream, val out_stream, val env) uw_push_handler(&uw_handler, cons(warning_s, nil), rw_f); + clear_error(in_stream); + line_w = linenoise(ls, c_str(prompt, self)); uw_pop_frame(&uw_handler); |