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..7ed362cb0b7 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -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,40 @@ 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 +726,40 @@ 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 with proper RT_null termination */ + rt_memmove(&shell->line[start], + &shell->line[start + del_count], + new_len - start + 1); // +1 包含 RT_null 终止符 + + /* 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; + + /* Full redraw for affected area */ + rt_kprintf("\033[%dD", del_count); // 左移删除长度 + rt_kprintf("%.*s", shell->line_position - start, &shell->line[start]); // 重写剩余内容 + rt_kprintf("\033[K"); // 清除行尾残留 + if (shell->line_position > start) + { + 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') {