Kaynağa Gözat

[update] <components>:finsh/shell.c
添加以下功能(需要kconfig使能FINSH_USING_WORD_OPERATION)
1 ctrl+back 按单词删除
2 ctrl+左右箭头 按单词切换光标

Signed-off-by: Yucai Liu <1486344514@qq.com>

liuyucai 3 ay önce
ebeveyn
işleme
236e830b65
2 değiştirilmiş dosya ile 110 ekleme ve 1 silme
  1. 6 0
      components/finsh/Kconfig
  2. 104 1
      components/finsh/shell.c

+ 6 - 0
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

+ 104 - 1
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')
         {