Skip to content

Commit f44b84e

Browse files
committed
feat(ansi): 添加终端控制ANSI转义宏,优化部分调用
1 parent f7a6986 commit f44b84e

2 files changed

Lines changed: 156 additions & 30 deletions

File tree

components/finsh/ansi.h

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* @file ansi.h
3+
* @brief VT100/xterm ANSI escape macros for serial terminal (e.g. Xshell).
4+
*
5+
* Usage:
6+
* uart_puts(ANSI_CLR_LINE);
7+
* uart_puts("log: ");
8+
* uart_puts(msg);
9+
* uart_puts(ANSI_CRLF);
10+
* redraw_prompt();
11+
*
12+
* Compile-time: uart_puts(ANSI_CLR_LINE);
13+
* Runtime: rt_kprintf(ANSI_FMT_CUB, n);
14+
*/
15+
16+
#ifndef ANSI_H
17+
#define ANSI_H
18+
19+
/* -------------------------------------------------------------------------- */
20+
/* Core */
21+
/* -------------------------------------------------------------------------- */
22+
23+
#define ANSI_ESC "\x1b"
24+
#define ANSI_CSI "\x1b["
25+
26+
#define ANSI_CRLF "\r\n"
27+
#define ANSI_CR "\r"
28+
#define ANSI_LF "\n"
29+
30+
/* -------------------------------------------------------------------------- */
31+
/* Erase */
32+
/* -------------------------------------------------------------------------- */
33+
34+
/** Clear from cursor to end of line */
35+
#define ANSI_EL ANSI_CSI "0K"
36+
/** Clear from line start to cursor */
37+
#define ANSI_EL_START ANSI_CSI "1K"
38+
/** Clear entire current line */
39+
#define ANSI_EL_LINE ANSI_CSI "2K"
40+
41+
/** Clear screen, cursor home (1,1) */
42+
#define ANSI_CLS ANSI_CSI "2J"
43+
/** Clear screen + scrollback (xterm) */
44+
#define ANSI_CLS_ALL ANSI_CSI "3J"
45+
46+
/** Carriage return + erase whole line (most used) */
47+
#define ANSI_CLR_LINE "\r" ANSI_EL_LINE
48+
49+
/* -------------------------------------------------------------------------- */
50+
/* Cursor move — parameterized (n must be decimal literal or macro) */
51+
/* -------------------------------------------------------------------------- */
52+
53+
#define ANSI_CUU(n) ANSI_CSI #n "A" /* cursor up */
54+
#define ANSI_CUD(n) ANSI_CSI #n "B" /* cursor down */
55+
#define ANSI_CUF(n) ANSI_CSI #n "C" /* cursor forward (right) */
56+
#define ANSI_CUB(n) ANSI_CSI #n "D" /* cursor back (left) */
57+
#define ANSI_CHA(n) ANSI_CSI #n "G" /* cursor column, 1-based */
58+
#define ANSI_CUP(row, col) ANSI_CSI #row ";" #col "H"
59+
60+
#define ANSI_CUU1 ANSI_CSI "1A"
61+
#define ANSI_CUD1 ANSI_CSI "1B"
62+
#define ANSI_CUF1 ANSI_CSI "1C"
63+
#define ANSI_CUB1 ANSI_CSI "1D"
64+
65+
/* -------------------------------------------------------------------------- */
66+
/* Cursor move — runtime (rt_kprintf / printf / snprintf, n >= 1) */
67+
/* -------------------------------------------------------------------------- */
68+
69+
#define ANSI_FMT_CUU ANSI_ESC "[%dA"
70+
#define ANSI_FMT_CUD ANSI_ESC "[%dB"
71+
#define ANSI_FMT_CUF ANSI_ESC "[%dC"
72+
#define ANSI_FMT_CUB ANSI_ESC "[%dD"
73+
#define ANSI_FMT_CHA ANSI_ESC "[%dG" /* column 1-based */
74+
#define ANSI_FMT_CUP ANSI_ESC "[%d;%dH" /* row, col; both 1-based */
75+
76+
/** Move to column n (1 = first column) — compile-time literal only */
77+
#define ANSI_COL(n) ANSI_CHA(n)
78+
79+
/**
80+
* Jump to end of current line without tracking column count.
81+
* Terminals clamp column to line width (works on Xshell VT100/xterm).
82+
*/
83+
#define ANSI_EOL ANSI_CSI "999C"
84+
#define ANSI_EOL_G ANSI_CSI "999G"
85+
86+
/* Save / restore cursor (optional; not all terminals support) */
87+
#define ANSI_SAVE_CURSOR ANSI_CSI "s"
88+
#define ANSI_RESTORE_CURSOR ANSI_CSI "u"
89+
90+
/* -------------------------------------------------------------------------- */
91+
/* SGR — text attributes */
92+
/* -------------------------------------------------------------------------- */
93+
94+
#define ANSI_RESET ANSI_CSI "0m"
95+
#define ANSI_BOLD ANSI_CSI "1m"
96+
#define ANSI_DIM ANSI_CSI "2m"
97+
#define ANSI_UNDERLINE ANSI_CSI "4m"
98+
#define ANSI_REVERSE ANSI_CSI "7m"
99+
100+
#define ANSI_FG_BLACK ANSI_CSI "30m"
101+
#define ANSI_FG_RED ANSI_CSI "31m"
102+
#define ANSI_FG_GREEN ANSI_CSI "32m"
103+
#define ANSI_FG_YELLOW ANSI_CSI "33m"
104+
#define ANSI_FG_BLUE ANSI_CSI "34m"
105+
#define ANSI_FG_MAGENTA ANSI_CSI "35m"
106+
#define ANSI_FG_CYAN ANSI_CSI "36m"
107+
#define ANSI_FG_WHITE ANSI_CSI "37m"
108+
109+
#define ANSI_BG_BLACK ANSI_CSI "40m"
110+
#define ANSI_BG_RED ANSI_CSI "41m"
111+
#define ANSI_BG_GREEN ANSI_CSI "42m"
112+
#define ANSI_BG_YELLOW ANSI_CSI "43m"
113+
#define ANSI_BG_BLUE ANSI_CSI "44m"
114+
#define ANSI_BG_MAGENTA ANSI_CSI "45m"
115+
#define ANSI_BG_CYAN ANSI_CSI "46m"
116+
#define ANSI_BG_WHITE ANSI_CSI "47m"
117+
118+
/* -------------------------------------------------------------------------- */
119+
/* Shell UI helpers (two-line layout: log above, prompt below) */
120+
/* -------------------------------------------------------------------------- */
121+
122+
/** Erase bottom interactive line (prompt + input); input kept in RAM. */
123+
#define ANSI_PROMPT_CLEAR ANSI_CLR_LINE
124+
125+
/**
126+
* After a log line exists above: go up one line and move to its end.
127+
* Then uart_puts() incremental log bytes, then ANSI_UI_NEWLINE + redraw prompt.
128+
*/
129+
#define ANSI_LOG_APPEND_POS ANSI_CUU1 ANSI_EOL
130+
131+
/** Separate log row from prompt row (structural newline, not log content). */
132+
#define ANSI_UI_NEWLINE ANSI_CRLF
133+
134+
/**
135+
* Overwrite current line in place (progress / status on one line).
136+
* uart_puts(ANSI_LINE_OVERWRITE); uart_puts("progress 50%");
137+
*/
138+
#define ANSI_LINE_OVERWRITE ANSI_CLR_LINE
139+
140+
#endif /* ANSI_H */

components/finsh/shell.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include <rthw.h>
2222
#include <string.h>
2323
#include <stdio.h>
24-
24+
#include "ansi.h"
2525
#ifdef RT_USING_FINSH
2626

2727
#include "shell.h"
@@ -409,7 +409,7 @@ static rt_bool_t shell_handle_history(struct finsh_shell *shell)
409409
rt_kprintf("\r");
410410

411411
#else
412-
rt_kprintf("\033[2K\r");
412+
rt_kprintf(ANSI_CLR_LINE);
413413
#endif
414414
rt_kprintf("%s%s", FINSH_PROMPT, shell->line);
415415
return RT_FALSE;
@@ -693,7 +693,7 @@ static void finsh_thread_entry(void *parameter)
693693
int new_pos = find_prev_word_start(shell->line, shell->line_curpos);
694694
if (new_pos != shell->line_curpos)
695695
{
696-
rt_kprintf("\033[%dD", shell->line_curpos - new_pos);
696+
rt_kprintf(ANSI_FMT_CUB, shell->line_curpos - new_pos);
697697
shell->line_curpos = new_pos;
698698
}
699699
continue;
@@ -703,7 +703,7 @@ static void finsh_thread_entry(void *parameter)
703703
int new_pos = find_next_word_end(shell->line, shell->line_curpos, shell->line_position);
704704
if (new_pos != shell->line_curpos)
705705
{
706-
rt_kprintf("\033[%dC", new_pos - shell->line_curpos);
706+
rt_kprintf(ANSI_FMT_CUF, new_pos - shell->line_curpos);
707707
shell->line_curpos = new_pos;
708708
}
709709
continue;
@@ -738,11 +738,8 @@ static void finsh_thread_entry(void *parameter)
738738
if (key_code == 0x31) /* home key */
739739
{
740740
/* move cursor to beginning of line */
741-
while (shell->line_curpos > 0)
742-
{
743-
rt_kprintf("\b");
744-
shell->line_curpos--;
745-
}
741+
rt_kprintf(ANSI_FMT_CUB, shell->line_curpos);
742+
shell->line_curpos = 0;
746743
}
747744
else if (key_code == 0x32) /* insert key */
748745
{
@@ -755,7 +752,6 @@ static void finsh_thread_entry(void *parameter)
755752
if (finsh_shell_check_line(shell) &&
756753
(shell->line_curpos < shell->line_position))
757754
{
758-
int i;
759755
shell->line_position--;
760756
rt_memmove(&shell->line[shell->line_curpos],
761757
&shell->line[shell->line_curpos + 1],
@@ -766,18 +762,14 @@ static void finsh_thread_entry(void *parameter)
766762
rt_kprintf("%s ", &shell->line[shell->line_curpos]);
767763

768764
/* move cursor back to original position */
769-
for (i = shell->line_curpos; i <= shell->line_position; i++)
770-
rt_kprintf("\b");
765+
rt_kprintf(ANSI_FMT_CUB, shell->line_position - shell->line_curpos + 1);
771766
}
772767
}
773768
else if (key_code == 0x34) /* end key */
774769
{
775770
/* move cursor to end of line */
776-
while (shell->line_curpos < shell->line_position)
777-
{
778-
rt_kprintf("%c", shell->line[shell->line_curpos]);
779-
shell->line_curpos++;
780-
}
771+
rt_kprintf(ANSI_FMT_CUF, shell->line_position-shell->line_curpos);
772+
shell->line_curpos = shell->line_position;
781773
}
782774
continue;
783775
}
@@ -792,10 +784,8 @@ static void finsh_thread_entry(void *parameter)
792784
/* handle tab key */
793785
else if (ch == '\t')
794786
{
795-
int i;
796787
/* move the cursor to the beginning of line */
797-
for (i = 0; i < shell->line_curpos; i++)
798-
rt_kprintf("\b");
788+
rt_kprintf(ANSI_FMT_CUB, shell->line_curpos);
799789

800790
/* auto complete */
801791
shell_auto_complete(&shell->line[0]);
@@ -816,8 +806,6 @@ static void finsh_thread_entry(void *parameter)
816806

817807
if (shell->line_position > shell->line_curpos)
818808
{
819-
int i;
820-
821809
rt_memmove(&shell->line[shell->line_curpos],
822810
&shell->line[shell->line_curpos + 1],
823811
shell->line_position - shell->line_curpos);
@@ -826,8 +814,7 @@ static void finsh_thread_entry(void *parameter)
826814
rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]);
827815

828816
/* move the cursor to the origin position */
829-
for (i = shell->line_curpos; i <= shell->line_position; i++)
830-
rt_kprintf("\b");
817+
rt_kprintf(ANSI_FMT_CUB, shell->line_position - shell->line_curpos + 1);
831818
}
832819
else
833820
{
@@ -860,15 +847,15 @@ static void finsh_thread_entry(void *parameter)
860847
shell->line_curpos = start;
861848

862849
/* Redraw the affected line section */
863-
rt_kprintf("\033[%dD", del_count);
850+
rt_kprintf(ANSI_FMT_CUB, del_count);
864851
/* Rewrite the remaining content */
865852
rt_kprintf("%.*s", shell->line_position - start, &shell->line[start]);
866853
/* Clear trailing artifacts */
867-
rt_kprintf("\033[K");
854+
rt_kprintf(ANSI_EL_LINE);
868855
if (shell->line_position > start)
869856
{
870857
/* Reset cursor */
871-
rt_kprintf("\033[%dD", shell->line_position - start);
858+
rt_kprintf(ANSI_FMT_CUB, shell->line_position - start);
872859
}
873860

874861
continue;
@@ -899,7 +886,6 @@ static void finsh_thread_entry(void *parameter)
899886
/* normal character */
900887
if (shell->line_curpos < shell->line_position)
901888
{
902-
int i;
903889
#if defined(FINSH_USING_FUNC_EXT)
904890
if (shell->overwrite_mode) /* overwrite mode */
905891
{
@@ -923,8 +909,8 @@ static void finsh_thread_entry(void *parameter)
923909
{
924910
rt_kprintf("%s", &shell->line[shell->line_curpos]);
925911
/* move cursor back to correct position */
926-
for (i = shell->line_curpos + 1; i < shell->line_position; i++)
927-
rt_kprintf("\b");
912+
if (shell->line_position > shell->line_curpos + 1)
913+
rt_kprintf(ANSI_FMT_CUB, shell->line_position - shell->line_curpos - 1);
928914
}
929915
shell->line_curpos++;
930916
}

0 commit comments

Comments
 (0)