[Concept,12/16] cli: Add multiline support to CLI line editing

Message ID 20260122041155.174721-13-sjg@u-boot.org
State New
Headers
Series expo: Add multiline editing support for textedit |

Commit Message

Simon Glass Jan. 22, 2026, 4:11 a.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Add support for multi-line input in CLI line editing:
- Add multiline bool to indicate input may contain multiple lines
- Add line_nav callback for Ctrl-P/N navigation between visual lines

When multiline is true, Ctrl-P/N call the line_nav callback instead of
accessing command history. The callback returns the new cursor position
or a negative value if at the boundary.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 common/cli_readline.c | 17 +++++++++++++++++
 include/cli.h         |  9 ++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)
  

Patch

diff --git a/common/cli_readline.c b/common/cli_readline.c
index 27fecd835a0..38f825184df 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -405,6 +405,23 @@  int cread_line_process_ch(struct cli_line_state *cls, char ichar)
 		break;
 	case CTL_CH('p'):
 	case CTL_CH('n'):
+		if (cls->multiline && cls->line_nav) {
+			int new_num;
+
+			new_num = cls->line_nav(cls, ichar == CTL_CH('p'));
+			if (new_num < 0) {
+				getcmd_cbeep(cls);
+				break;
+			}
+
+			/*
+			 * Just update the position - the callback handles
+			 * cursor display since backspaces don't work across
+			 * wrapped line boundaries
+			 */
+			cls->num = new_num;
+			break;
+		}
 		if (cls->history) {
 			char *hline;
 
diff --git a/include/cli.h b/include/cli.h
index a02e228bf8a..f1e5887fa56 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -34,10 +34,15 @@  struct cli_ch_state {
  * @history: true if history should be accessible
  * @cmd_complete: true if tab completion should be enabled (requires @prompt to
  *	be set)
+ * @multiline: true if input may contain multiple lines (enables Ctrl-P/N for
+ *	line navigation instead of history)
  * @buf: Buffer containing line
  * @prompt: Prompt for the line
  * @putch: Function to call to output a character (NULL to use putc())
- * @priv: Private data for putch callback
+ * @line_nav: Function to call for multi-line navigation (Ctrl-P/N). Called with
+ *	@up true for previous line, false for next. Returns new cursor position,
+ *	or -ve if at boundary
+ * @priv: Private data for callbacks
  */
 struct cli_line_state {
 	uint num;
@@ -46,9 +51,11 @@  struct cli_line_state {
 	bool insert;
 	bool history;
 	bool cmd_complete;
+	bool multiline;
 	char *buf;
 	const char *prompt;
 	void (*putch)(struct cli_line_state *cls, int ch);
+	int (*line_nav)(struct cli_line_state *cls, bool up);
 	void *priv;
 };