From 86a73822c12bcdb40cad20f5e67ad3aa294a452a Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sun, 1 Aug 2021 14:43:57 -0700 Subject: listener: support multi-line expressions in plain mode. * linenoise/linenoise.c (linenoise): If we are in noninteractive mode, then do not just read one line and return it. If an enter_callback is defined then keep accumulating lines while the callback indicates incomplete syntax, until EOF occurs or the syntax appears complete. Return the lines glued together, with \n characters replaced by \r, so the line is correctly entered into the history, and the trailing LF obliterated, as usual. * txr.1: Documented new multi-line behavior of plain mode. --- linenoise/linenoise.c | 44 ++++++++++++++++++++++++++++++++++++-------- txr.1 | 8 ++++++++ 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index 99af2418..c25014cf 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -2528,17 +2528,45 @@ wchar_t *linenoise(lino_t *ls, const wchar_t *prompt) int ifd = lino_os.fileno_fn(ls->tty_ifs); if ( ls->noninteractive || !isatty(ifd)) { - /* Not a tty: read from file / pipe. */ - if (lino_os.getl_fn(ls->tty_ifs, ls->data, nelem(ls->data)) == 0) { - ls->error = (lino_os.eof_fn(ls->tty_ifs) ? lino_eof : lino_ioerr); - return 0; + wchar_t *ret = 0; + size_t len = 0, i; + + for (;;) { + size_t nlen; + /* Not a tty: read from file / pipe. */ + if (lino_os.getl_fn(ls->tty_ifs, ls->data, nelem(ls->data)) == 0) { + ls->error = (lino_os.eof_fn(ls->tty_ifs) ? lino_eof : lino_ioerr); + break; + } + + nlen = wcslen(ls->data); + + { + wchar_t *nret = lino_os.wrealloc_fn(ret, len + nlen + 1); + if (nret == 0) { + lino_os.free_fn(ret); + return 0; + } + wmemcpy(nret + len, ls->data, nlen + 1); + ret = nret; + len = len + nlen; + } + + if (!ls->enter_callback || ls->enter_callback(ret, ls->ce_ctx)) + break; } - count = wcslen(ls->data); + if (ret != 0) { + if (len && ret[len - 1] == '\n') + ret[len-1] = '\0'; - if (count && ls->data[count-1] == '\n') - ls->data[count-1] = '\0'; - return lino_os.wstrdup_fn(ls->data); + for (i = 0; i < len; i++) { + if (ret[i] == '\n') + ret[i] = '\r'; + } + } + + return ret; } else { wchar_t *ret = 0; #ifdef SIGWINCH diff --git a/txr.1 b/txr.1 index 91dc6042..62c791df 100644 --- a/txr.1 +++ b/txr.1 @@ -82547,6 +82547,14 @@ for accessing evaluation results are established. Lines are still entered into the history, and the interactive profile is still processed, as usual. +Plain mode reads whole lines of input, yet recognizes multi-line expressions. +Whenever a line of input is read which represents incomplete syntax, another +line of input is read and appended to that line. This repeats until the +accumulated input represents complete syntax, and is then processed as a unit. + +Each unit of input is expected to represent a single expression, otherwise +an error is diagnosed. + .SS* Interactive Profile File Unless the -- cgit v1.2.3