Add a new Kconfig option CONFIG_CMDLINE_EDITOR to enable enhanced command-line editing features. This replaces CLI_READLINE_CALLBACK and is enabled by default when EXPO is enabled. Create struct cli_editor_state to hold state for enhanced editing features, initially containing: - putch: callback for character output redirection - line_nav: callback for multi-line navigation (Ctrl-P/N) - multiline: flag for multi-line input mode This struct is embedded in cli_line_state when CMDLINE_EDITOR is enabled. Add cli_editor() accessor function that returns a pointer to the editor state, or NULL if CMDLINE_EDITOR is not enabled. Update cli_readline.c and scene_txtin.c to use the new accessor. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- boot/scene_txtin.c | 10 ++++--- cmd/Kconfig | 16 +++++++---- common/cli_readline.c | 12 +++++--- include/cli.h | 66 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/boot/scene_txtin.c b/boot/scene_txtin.c index cde9fdb8ccf..79814891cdc 100644 --- a/boot/scene_txtin.c +++ b/boot/scene_txtin.c @@ -112,6 +112,7 @@ int scene_txtin_render_deps(struct scene *scn, struct scene_obj *obj, struct scene_txtin *tin) { struct cli_line_state *cls = &tin->cls; + struct cli_editor_state *ed = cli_editor(cls); const bool open = obj->flags & SCENEOF_OPEN; struct udevice *cons = scn->expo->cons; void *ctx = tin->ctx; @@ -121,7 +122,7 @@ int scene_txtin_render_deps(struct scene *scn, struct scene_obj *obj, if (open) { scene_render_obj(scn, tin->edit_id, ctx); - if (cls->multiline) { + if (ed->multiline) { /* for multiline, set cursor position directly */ struct scene_obj_txt *txt; @@ -260,6 +261,7 @@ int scene_txtin_open(struct scene *scn, struct scene_obj *obj, struct scene_txtin *tin) { struct cli_line_state *cls = &tin->cls; + struct cli_editor_state *ed = cli_editor(cls); struct udevice *cons = scn->expo->cons; struct scene_obj_txt *txt; void *ctx; @@ -286,11 +288,11 @@ int scene_txtin_open(struct scene *scn, struct scene_obj *obj, vidconsole_entry_start(cons, ctx); cli_cread_init(cls, abuf_data(&tin->buf), abuf_size(&tin->buf)); cls->insert = true; - cls->putch = scene_txtin_putch; + ed->putch = scene_txtin_putch; cls->priv = scn; if (obj->type == SCENEOBJT_TEXTEDIT) { - cls->multiline = true; - cls->line_nav = scene_txtin_line_nav; + ed->multiline = true; + ed->line_nav = scene_txtin_line_nav; } cli_cread_add_initial(cls); diff --git a/cmd/Kconfig b/cmd/Kconfig index d8f57c446a5..448a6e9fe39 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -54,13 +54,17 @@ config CMDLINE_EDITING Enable editing and History functions for interactive command line input operations -config CLI_READLINE_CALLBACK - bool "Support a callback for character output" +config CMDLINE_EDITOR + bool "Enhanced command-line editing features" depends on CMDLINE_EDITING - help - Enable a callback for character output during line editing. This - allows redirection of output to a different destination, such as - a vidconsole. This is used by expo to support textline editing. + default y if EXPO + help + Enable enhanced editing features for the command line, including: + - Character-output callback for redirection to vidconsole + - Multi-line navigation callback (Ctrl-P/N) + - Ctrl+Left/Right arrow keys to move by words + - Undo/redo support (Ctrl+Z / Ctrl+Shift+Z) + - Yank/paste of killed text (Ctrl+Y) config CMDLINE_PS_SUPPORT bool "Enable support for changing the command prompt string at run-time" diff --git a/common/cli_readline.c b/common/cli_readline.c index 38f825184df..d2b02933fd7 100644 --- a/common/cli_readline.c +++ b/common/cli_readline.c @@ -79,8 +79,10 @@ static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen) */ static void cls_putch(struct cli_line_state *cls, int ch) { - if (CONFIG_IS_ENABLED(CLI_READLINE_CALLBACK) && cls->putch) - cls->putch(cls, ch); + struct cli_editor_state *ed = cli_editor(cls); + + if (ed && ed->putch) + ed->putch(cls, ch); else putc(ch); } @@ -299,6 +301,7 @@ static void cread_add_str(struct cli_line_state *cls, char *str, int strsize, int cread_line_process_ch(struct cli_line_state *cls, char ichar) { + struct cli_editor_state *ed; char *buf = cls->buf; /* ichar=0x0 when error occurs in U-Boot getc */ @@ -405,10 +408,11 @@ 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) { + ed = cli_editor(cls); + if (ed && ed->multiline && ed->line_nav) { int new_num; - new_num = cls->line_nav(cls, ichar == CTL_CH('p')); + new_num = ed->line_nav(cls, ichar == CTL_CH('p')); if (new_num < 0) { getcmd_cbeep(cls); break; diff --git a/include/cli.h b/include/cli.h index f1e5887fa56..b6a8a6be1dd 100644 --- a/include/cli.h +++ b/include/cli.h @@ -25,6 +25,43 @@ struct cli_ch_state { bool emitting; }; +struct cli_line_state; + +/** + * struct cli_editor_state - state for enhanced editing features + * + * This is only available when CONFIG_CMDLINE_EDITOR is enabled. + * + * @putch: Output a character (NULL to use putc()) + * @line_nav: Handle multi-line navigation (Ctrl-P/N) + * @multiline: true if input may contain multiple lines (enables + * Ctrl-P/N for line navigation instead of history) + */ +struct cli_editor_state { + /** + * @putch: Output a character (NULL to use putc()) + * + * @cls: CLI line state + * @ch: Character to output + */ + void (*putch)(struct cli_line_state *cls, int ch); + + /** + * @line_nav: Handle multi-line navigation (Ctrl-P/N) + * + * @cls: CLI line state + * @up: true for previous line, false for next + * Return: new cursor position, or -ve if at boundary + */ + int (*line_nav)(struct cli_line_state *cls, bool up); + + /** + * @multiline: true if input may contain multiple lines (enables + * Ctrl-P/N for line navigation instead of history) + */ + bool multiline; +}; + /** * struct cli_line_state - state of the line editor * @@ -34,15 +71,10 @@ 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()) - * @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 + * @ed: Editor state for enhanced features (if CONFIG_CMDLINE_EDITOR) */ struct cli_line_state { uint num; @@ -51,14 +83,30 @@ 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; +#if CONFIG_IS_ENABLED(CMDLINE_EDITOR) + struct cli_editor_state ed; +#endif }; +/** + * cli_editor() - Get the editor state from a line state + * + * @cls: CLI line state + * Return: Pointer to editor state, or NULL if CONFIG_CMDLINE_EDITOR is not + * enabled + */ +static inline struct cli_editor_state *cli_editor(struct cli_line_state *cls) +{ +#if CONFIG_IS_ENABLED(CMDLINE_EDITOR) + return &cls->ed; +#else + return NULL; +#endif +} + /** * Go into the command loop * -- 2.43.0