|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2006-2021, RT-Thread Development Team |
| 2 | + * Copyright (c) 2006-2025, RT-Thread Development Team |
3 | 3 | *
|
4 | 4 | * SPDX-License-Identifier: Apache-2.0
|
5 | 5 | *
|
@@ -457,6 +457,37 @@ static void shell_push_history(struct finsh_shell *shell)
|
457 | 457 | }
|
458 | 458 | #endif
|
459 | 459 |
|
| 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 | + |
460 | 491 | #ifdef RT_USING_HOOK
|
461 | 492 | static void (*_finsh_thread_entry_hook)(void);
|
462 | 493 |
|
@@ -609,6 +640,42 @@ static void finsh_thread_entry(void *parameter)
|
609 | 640 |
|
610 | 641 | continue;
|
611 | 642 | }
|
| 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) */ |
612 | 679 | }
|
613 | 680 |
|
614 | 681 | /* received null or error */
|
@@ -661,7 +728,43 @@ static void finsh_thread_entry(void *parameter)
|
661 | 728 |
|
662 | 729 | continue;
|
663 | 730 | }
|
| 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 | + } |
664 | 764 |
|
| 765 | + continue; |
| 766 | + } |
| 767 | +#endif /*defined(FINSH_USING_WORD_OPERATION) */ |
665 | 768 | /* handle end of line, break */
|
666 | 769 | if (ch == '\r' || ch == '\n')
|
667 | 770 | {
|
|
0 commit comments