From 1f7600eaf8b2ec8c40e92b0f3819679610963ea1 Mon Sep 17 00:00:00 2001 From: liuyucai <1486344514@qq.com> Date: Fri, 13 Jun 2025 20:25:50 +0800 Subject: [PATCH] =?UTF-8?q?[update]=20:finsh/shell.c=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=A5=E4=B8=8B=E5=8A=9F=E8=83=BD(?= =?UTF-8?q?=E9=9C=80=E8=A6=81kconfig=E4=BD=BF=E8=83=BDFINSH=5FUSING=5FWORD?= =?UTF-8?q?=5FOPERATION)=201=20ctrl+back=20=E6=8C=89=E5=8D=95=E8=AF=8D?= =?UTF-8?q?=E5=88=A0=E9=99=A4=202=20ctrl+=E5=B7=A6=E5=8F=B3=E7=AE=AD?= =?UTF-8?q?=E5=A4=B4=20=E6=8C=89=E5=8D=95=E8=AF=8D=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=85=89=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yucai Liu <1486344514@qq.com> --- components/finsh/Kconfig | 6 +++ components/finsh/shell.c | 105 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/components/finsh/Kconfig b/components/finsh/Kconfig index abae556dd2d..c99ce6a8d52 100644 --- a/components/finsh/Kconfig +++ b/components/finsh/Kconfig @@ -35,6 +35,12 @@ if RT_USING_MSH default 5 endif + config FINSH_USING_WORD_OPERATION + bool "Enable word-based cursor operations" + default n + help + Enable Ctrl+Backspace to delete words and Ctrl+Arrow to move cursor by word + config FINSH_USING_SYMTAB bool "Using symbol table for commands" default y diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 2b9349364c5..bb5fa776b28 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2025, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -457,6 +457,37 @@ static void shell_push_history(struct finsh_shell *shell) } #endif +#if defined(FINSH_USING_WORD_OPERATION) +static int find_prev_word_start(const char *line, int curpos) +{ + if (curpos <= 0) return 0; + + /* Skip whitespace */ + while (--curpos > 0 && (line[curpos] == ' ' || line[curpos] == '\t')); + + /* Find word start */ + while (curpos > 0 && !(line[curpos] == ' ' || line[curpos] == '\t')) + curpos--; + + return (curpos <= 0) ? 0 : curpos + 1; +} + +static int find_next_word_end(const char *line, int curpos, int max) +{ + if (curpos >= max) return max; + + /* Skip to next word */ + while (curpos < max && (line[curpos] == ' ' || line[curpos] == '\t')) + curpos++; + + /* Find word end */ + while (curpos < max && !(line[curpos] == ' ' || line[curpos] == '\t')) + curpos++; + + return curpos; +} +#endif /* defined(FINSH_USING_WORD_OPERATION) */ + #ifdef RT_USING_HOOK static void (*_finsh_thread_entry_hook)(void); @@ -609,6 +640,42 @@ static void finsh_thread_entry(void *parameter) continue; } +#if defined(FINSH_USING_WORD_OPERATION) + /* Add Ctrl+Left/Right handling */ + else if (ch == '1') + { + /* Read modifier sequence [1;5D/C] */ + int next_ch = finsh_getchar(); + if (next_ch == ';') + { + next_ch = finsh_getchar(); + if (next_ch == '5') + { + next_ch = finsh_getchar(); + if (next_ch == 'D') /* Ctrl+Left */ + { + int new_pos = find_prev_word_start(shell->line, shell->line_curpos); + if (new_pos != shell->line_curpos) + { + rt_kprintf("\033[%dD", shell->line_curpos - new_pos); + shell->line_curpos = new_pos; + } + continue; + } + else if (next_ch == 'C') /* Ctrl+Right */ + { + int new_pos = find_next_word_end(shell->line, shell->line_curpos, shell->line_position); + if (new_pos != shell->line_curpos) + { + rt_kprintf("\033[%dC", new_pos - shell->line_curpos); + shell->line_curpos = new_pos; + } + continue; + } + } + } + } +#endif /*defined(FINSH_USING_WORD_OPERATION) */ } /* received null or error */ @@ -661,7 +728,43 @@ static void finsh_thread_entry(void *parameter) continue; } +#if defined(FINSH_USING_WORD_OPERATION) + /* Add Ctrl+Backspace handling */ + else if (ch == 0x17) /* Ctrl+Backspace (typically ^W) */ + { + if (shell->line_curpos == 0) continue; + + int start = find_prev_word_start(shell->line, shell->line_curpos); + int del_count = shell->line_curpos - start; + int new_len = shell->line_position - del_count; + + /* Delete characters and properly add RT_NULL termination */ + rt_memmove(&shell->line[start], + &shell->line[start + del_count], + new_len - start + 1); + + /* Clear residual data */ + rt_memset(&shell->line[new_len], 0, shell->line_position - new_len); + + /* Update positions */ + shell->line_position = new_len; + shell->line_curpos = start; + + /* Redraw the affected line section */ + rt_kprintf("\033[%dD", del_count); + /* Rewrite the remaining content */ + rt_kprintf("%.*s", shell->line_position - start, &shell->line[start]); + /* Clear trailing artifacts */ + rt_kprintf("\033[K"); + if (shell->line_position > start) + { + /* Reset cursor */ + rt_kprintf("\033[%dD", shell->line_position - start); + } + continue; + } +#endif /*defined(FINSH_USING_WORD_OPERATION) */ /* handle end of line, break */ if (ch == '\r' || ch == '\n') {