Skip to content

Commit 1f7600e

Browse files
[update] <components>:finsh/shell.c
添加以下功能(需要kconfig使能FINSH_USING_WORD_OPERATION) 1 ctrl+back 按单词删除 2 ctrl+左右箭头 按单词切换光标 Signed-off-by: Yucai Liu <1486344514@qq.com>
1 parent 169d84d commit 1f7600e

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

components/finsh/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ if RT_USING_MSH
3535
default 5
3636
endif
3737

38+
config FINSH_USING_WORD_OPERATION
39+
bool "Enable word-based cursor operations"
40+
default n
41+
help
42+
Enable Ctrl+Backspace to delete words and Ctrl+Arrow to move cursor by word
43+
3844
config FINSH_USING_SYMTAB
3945
bool "Using symbol table for commands"
4046
default y

components/finsh/shell.c

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2006-2021, RT-Thread Development Team
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*
@@ -457,6 +457,37 @@ static void shell_push_history(struct finsh_shell *shell)
457457
}
458458
#endif
459459

460+
#if defined(FINSH_USING_WORD_OPERATION)
461+
static int find_prev_word_start(const char *line, int curpos)
462+
{
463+
if (curpos <= 0) return 0;
464+
465+
/* Skip whitespace */
466+
while (--curpos > 0 && (line[curpos] == ' ' || line[curpos] == '\t'));
467+
468+
/* Find word start */
469+
while (curpos > 0 && !(line[curpos] == ' ' || line[curpos] == '\t'))
470+
curpos--;
471+
472+
return (curpos <= 0) ? 0 : curpos + 1;
473+
}
474+
475+
static int find_next_word_end(const char *line, int curpos, int max)
476+
{
477+
if (curpos >= max) return max;
478+
479+
/* Skip to next word */
480+
while (curpos < max && (line[curpos] == ' ' || line[curpos] == '\t'))
481+
curpos++;
482+
483+
/* Find word end */
484+
while (curpos < max && !(line[curpos] == ' ' || line[curpos] == '\t'))
485+
curpos++;
486+
487+
return curpos;
488+
}
489+
#endif /* defined(FINSH_USING_WORD_OPERATION) */
490+
460491
#ifdef RT_USING_HOOK
461492
static void (*_finsh_thread_entry_hook)(void);
462493

@@ -609,6 +640,42 @@ static void finsh_thread_entry(void *parameter)
609640

610641
continue;
611642
}
643+
#if defined(FINSH_USING_WORD_OPERATION)
644+
/* Add Ctrl+Left/Right handling */
645+
else if (ch == '1')
646+
{
647+
/* Read modifier sequence [1;5D/C] */
648+
int next_ch = finsh_getchar();
649+
if (next_ch == ';')
650+
{
651+
next_ch = finsh_getchar();
652+
if (next_ch == '5')
653+
{
654+
next_ch = finsh_getchar();
655+
if (next_ch == 'D') /* Ctrl+Left */
656+
{
657+
int new_pos = find_prev_word_start(shell->line, shell->line_curpos);
658+
if (new_pos != shell->line_curpos)
659+
{
660+
rt_kprintf("\033[%dD", shell->line_curpos - new_pos);
661+
shell->line_curpos = new_pos;
662+
}
663+
continue;
664+
}
665+
else if (next_ch == 'C') /* Ctrl+Right */
666+
{
667+
int new_pos = find_next_word_end(shell->line, shell->line_curpos, shell->line_position);
668+
if (new_pos != shell->line_curpos)
669+
{
670+
rt_kprintf("\033[%dC", new_pos - shell->line_curpos);
671+
shell->line_curpos = new_pos;
672+
}
673+
continue;
674+
}
675+
}
676+
}
677+
}
678+
#endif /*defined(FINSH_USING_WORD_OPERATION) */
612679
}
613680

614681
/* received null or error */
@@ -661,7 +728,43 @@ static void finsh_thread_entry(void *parameter)
661728

662729
continue;
663730
}
731+
#if defined(FINSH_USING_WORD_OPERATION)
732+
/* Add Ctrl+Backspace handling */
733+
else if (ch == 0x17) /* Ctrl+Backspace (typically ^W) */
734+
{
735+
if (shell->line_curpos == 0) continue;
736+
737+
int start = find_prev_word_start(shell->line, shell->line_curpos);
738+
int del_count = shell->line_curpos - start;
739+
int new_len = shell->line_position - del_count;
740+
741+
/* Delete characters and properly add RT_NULL termination */
742+
rt_memmove(&shell->line[start],
743+
&shell->line[start + del_count],
744+
new_len - start + 1);
745+
746+
/* Clear residual data */
747+
rt_memset(&shell->line[new_len], 0, shell->line_position - new_len);
748+
749+
/* Update positions */
750+
shell->line_position = new_len;
751+
shell->line_curpos = start;
752+
753+
/* Redraw the affected line section */
754+
rt_kprintf("\033[%dD", del_count);
755+
/* Rewrite the remaining content */
756+
rt_kprintf("%.*s", shell->line_position - start, &shell->line[start]);
757+
/* Clear trailing artifacts */
758+
rt_kprintf("\033[K");
759+
if (shell->line_position > start)
760+
{
761+
/* Reset cursor */
762+
rt_kprintf("\033[%dD", shell->line_position - start);
763+
}
664764

765+
continue;
766+
}
767+
#endif /*defined(FINSH_USING_WORD_OPERATION) */
665768
/* handle end of line, break */
666769
if (ch == '\r' || ch == '\n')
667770
{

0 commit comments

Comments
 (0)