From cfd11a27aed69fec13d76135b45859554bf1f627 Mon Sep 17 00:00:00 2001
From: Kaz Kylheku <kaz@kylheku.com>
Date: Tue, 3 Aug 2021 06:50:38 -0700
Subject: listener: prompt feature for plain mode.

The :prompt-on command will enable prompting in plain mode.

* linenoise/linenoise.c (struct lino_state): New member, show_prompt.
(line_enable_noninteractive_prompt): New function.
(linenoise): In the plain mode loop, the show_prompt flag is on, show
the prompt. For continuation lines, show a condensed prompt, which
consists of the suffix of the full prompt, starting on the last
non-whitespace character.

* linenoise/linenoise.h (lino_enable_noninteractive): Declared.

* parser.c (repl): Implement :prompt-on command which enables the
above mode.

* txr.1: Documented.
---
 linenoise/linenoise.c | 19 +++++++++++++++++++
 linenoise/linenoise.h |  1 +
 2 files changed, 20 insertions(+)

(limited to 'linenoise')

diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c
index c25014cf..266542c1 100644
--- a/linenoise/linenoise.c
+++ b/linenoise/linenoise.c
@@ -137,6 +137,7 @@ struct lino_state {
     int selmode;        /* Visual selection being made. */
     int selinclusive;   /* Selections include character right of endpoint. */
     int noninteractive; /* No character editing, even if input is tty. */
+    int show_prompt;    /* Show prompting in non-interactive mode. */
     struct lino_undo *undo_stack;
     lino_error_t error; /* Most recent error. */
 };
@@ -207,6 +208,11 @@ int lino_get_noninteractive(lino_t *ls)
     return ls->noninteractive;
 }
 
+void lino_enable_noninteractive_prompt(lino_t *ls, int enable)
+{
+    ls->show_prompt = enable;
+}
+
 void lino_set_atom_cb(lino_t *l, lino_atom_cb_t *cb, void *ctx)
 {
     l->atom_callback = cb;
@@ -2530,9 +2536,22 @@ wchar_t *linenoise(lino_t *ls, const wchar_t *prompt)
     if ( ls->noninteractive || !isatty(ifd)) {
         wchar_t *ret = 0;
         size_t len = 0, i;
+        const wchar_t *condensed_prompt = prompt + wcslen(prompt);
+
+        if (ls->show_prompt) {
+            while (condensed_prompt > prompt &&
+                   (*condensed_prompt == 0 || *condensed_prompt == ' '))
+            {
+                condensed_prompt--;
+            }
+        }
 
         for (;;) {
             size_t nlen;
+
+            if (ls->show_prompt)
+                lino_os.puts_fn(ls->tty_ofs, ret ? condensed_prompt : prompt);
+
             /* 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);
diff --git a/linenoise/linenoise.h b/linenoise/linenoise.h
index 151ee99c..7fef68d9 100644
--- a/linenoise/linenoise.h
+++ b/linenoise/linenoise.h
@@ -124,6 +124,7 @@ void lino_set_selinclusive(lino_t *, int si);
 int lino_get_selinculsive(lino_t *);
 void lino_set_noninteractive(lino_t *, int ni);
 int lino_get_noninteractive(lino_t *);
+void lino_enable_noninteractive_prompt(lino_t *, int enable);
 
 typedef wchar_t *lino_atom_cb_t(lino_t *, const wchar_t *line, int n, void *ctx);
 void lino_set_atom_cb(lino_t *, lino_atom_cb_t *, void *ctx);
-- 
cgit v1.2.3