|
1 | 1 | #include <stdlib.h> |
2 | | -#include <string.h> |
3 | 2 | #include <stdio.h> |
4 | 3 |
|
5 | 4 | #include <stm32f4xx_hal.h> |
|
19 | 18 | #include "gc.h" |
20 | 19 | #include "gccollect.h" |
21 | 20 | #include "systick.h" |
| 21 | +#include "pybstdio.h" |
| 22 | +#include "readline.h" |
22 | 23 | #include "pyexec.h" |
23 | 24 | #include "storage.h" |
24 | 25 | #include "usb.h" |
25 | | -#include "usart.h" |
26 | 26 |
|
27 | 27 | pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; |
28 | 28 | STATIC bool repl_display_debugging_info = 0; |
29 | 29 |
|
30 | | -void stdout_tx_str(const char *str) { |
31 | | - if (pyb_usart_global_debug != PYB_USART_NONE) { |
32 | | - usart_tx_str(pyb_usart_global_debug, str); |
33 | | - } |
34 | | -#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD |
35 | | - lcd_print_str(str); |
36 | | -#endif |
37 | | - usb_vcp_send_str(str); |
38 | | -} |
39 | | - |
40 | | -void stdout_tx_strn(const char *str, uint len) { |
41 | | - if (pyb_usart_global_debug != PYB_USART_NONE) { |
42 | | - usart_tx_strn(pyb_usart_global_debug, str, len); |
43 | | - } |
44 | | -#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD |
45 | | - lcd_print_strn(str, len); |
46 | | -#endif |
47 | | - usb_vcp_send_strn(str, len); |
48 | | -} |
49 | | - |
50 | | -int stdin_rx_chr(void) { |
51 | | - for (;;) { |
52 | | -#if 0 |
53 | | -#ifdef USE_HOST_MODE |
54 | | - pyb_usb_host_process(); |
55 | | - int c = pyb_usb_host_get_keyboard(); |
56 | | - if (c != 0) { |
57 | | - return c; |
58 | | - } |
59 | | -#endif |
60 | | -#endif |
61 | | - if (usb_vcp_rx_num() != 0) { |
62 | | - return usb_vcp_rx_get(); |
63 | | - } else if (pyb_usart_global_debug != PYB_USART_NONE && usart_rx_any(pyb_usart_global_debug)) { |
64 | | - return usart_rx_char(pyb_usart_global_debug); |
65 | | - } |
66 | | - HAL_Delay(1); |
67 | | - if (storage_needs_flush()) { |
68 | | - storage_flush(); |
69 | | - } |
70 | | - } |
71 | | -} |
72 | | - |
73 | | -char *str_dup(const char *str) { |
74 | | - uint32_t len = strlen(str); |
75 | | - char *s2 = m_new(char, len + 1); |
76 | | - memcpy(s2, str, len); |
77 | | - s2[len] = 0; |
78 | | - return s2; |
79 | | -} |
80 | | - |
81 | | -#define READLINE_HIST_SIZE (8) |
82 | | - |
83 | | -static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; |
84 | | - |
85 | | -int readline(vstr_t *line, const char *prompt) { |
86 | | - stdout_tx_str(prompt); |
87 | | - int orig_line_len = line->len; |
88 | | - int escape_seq = 0; |
89 | | - int hist_cur = -1; |
90 | | - int cursor_pos = orig_line_len; |
91 | | - for (;;) { |
92 | | - int c = stdin_rx_chr(); |
93 | | - int last_line_len = line->len; |
94 | | - int redraw_step_back = 0; |
95 | | - bool redraw_from_cursor = false; |
96 | | - int redraw_step_forward = 0; |
97 | | - if (escape_seq == 0) { |
98 | | - if (VCP_CHAR_CTRL_A <= c && c <= VCP_CHAR_CTRL_D && vstr_len(line) == orig_line_len) { |
99 | | - // control character with empty line |
100 | | - return c; |
101 | | - } else if (c == '\r') { |
102 | | - // newline |
103 | | - stdout_tx_str("\r\n"); |
104 | | - if (line->len > orig_line_len && (readline_hist[0] == NULL || strcmp(readline_hist[0], line->buf + orig_line_len) != 0)) { |
105 | | - // a line which is not empty and different from the last one |
106 | | - // so update the history |
107 | | - for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { |
108 | | - readline_hist[i] = readline_hist[i - 1]; |
109 | | - } |
110 | | - readline_hist[0] = str_dup(line->buf + orig_line_len); |
111 | | - } |
112 | | - return 0; |
113 | | - } else if (c == 27) { |
114 | | - // escape sequence |
115 | | - escape_seq = 1; |
116 | | - } else if (c == 127) { |
117 | | - // backspace |
118 | | - if (cursor_pos > orig_line_len) { |
119 | | - vstr_cut_out_bytes(line, cursor_pos - 1, 1); |
120 | | - // set redraw parameters |
121 | | - redraw_step_back = 1; |
122 | | - redraw_from_cursor = true; |
123 | | - } |
124 | | - } else if (32 <= c && c <= 126) { |
125 | | - // printable character |
126 | | - vstr_ins_char(line, cursor_pos, c); |
127 | | - // set redraw parameters |
128 | | - redraw_from_cursor = true; |
129 | | - redraw_step_forward = 1; |
130 | | - } |
131 | | - } else if (escape_seq == 1) { |
132 | | - if (c == '[') { |
133 | | - escape_seq = 2; |
134 | | - } else { |
135 | | - escape_seq = 0; |
136 | | - } |
137 | | - } else if (escape_seq == 2) { |
138 | | - escape_seq = 0; |
139 | | - if (c == 'A') { |
140 | | - // up arrow |
141 | | - if (hist_cur + 1 < READLINE_HIST_SIZE && readline_hist[hist_cur + 1] != NULL) { |
142 | | - // increase hist num |
143 | | - hist_cur += 1; |
144 | | - // set line to history |
145 | | - line->len = orig_line_len; |
146 | | - vstr_add_str(line, readline_hist[hist_cur]); |
147 | | - // set redraw parameters |
148 | | - redraw_step_back = cursor_pos - orig_line_len; |
149 | | - redraw_from_cursor = true; |
150 | | - redraw_step_forward = line->len - orig_line_len; |
151 | | - } |
152 | | - } else if (c == 'B') { |
153 | | - // down arrow |
154 | | - if (hist_cur >= 0) { |
155 | | - // decrease hist num |
156 | | - hist_cur -= 1; |
157 | | - // set line to history |
158 | | - vstr_cut_tail_bytes(line, line->len - orig_line_len); |
159 | | - if (hist_cur >= 0) { |
160 | | - vstr_add_str(line, readline_hist[hist_cur]); |
161 | | - } |
162 | | - // set redraw parameters |
163 | | - redraw_step_back = cursor_pos - orig_line_len; |
164 | | - redraw_from_cursor = true; |
165 | | - redraw_step_forward = line->len - orig_line_len; |
166 | | - } |
167 | | - } else if (c == 'C') { |
168 | | - // right arrow |
169 | | - if (cursor_pos < line->len) { |
170 | | - redraw_step_forward = 1; |
171 | | - } |
172 | | - } else if (c == 'D') { |
173 | | - // left arrow |
174 | | - if (cursor_pos > orig_line_len) { |
175 | | - redraw_step_back = 1; |
176 | | - } |
177 | | - } |
178 | | - } else { |
179 | | - escape_seq = 0; |
180 | | - } |
181 | | - |
182 | | - // redraw command prompt, efficiently |
183 | | - if (redraw_step_back > 0) { |
184 | | - for (int i = 0; i < redraw_step_back; i++) { |
185 | | - stdout_tx_str("\b"); |
186 | | - } |
187 | | - cursor_pos -= redraw_step_back; |
188 | | - } |
189 | | - if (redraw_from_cursor) { |
190 | | - if (line->len < last_line_len) { |
191 | | - // erase old chars |
192 | | - for (int i = cursor_pos; i < last_line_len; i++) { |
193 | | - stdout_tx_str(" "); |
194 | | - } |
195 | | - // step back |
196 | | - for (int i = cursor_pos; i < last_line_len; i++) { |
197 | | - stdout_tx_str("\b"); |
198 | | - } |
199 | | - } |
200 | | - // draw new chars |
201 | | - stdout_tx_strn(line->buf + cursor_pos, line->len - cursor_pos); |
202 | | - // move cursor forward if needed (already moved forward by length of line, so move it back) |
203 | | - for (int i = cursor_pos + redraw_step_forward; i < line->len; i++) { |
204 | | - stdout_tx_str("\b"); |
205 | | - } |
206 | | - cursor_pos += redraw_step_forward; |
207 | | - } else if (redraw_step_forward > 0) { |
208 | | - // draw over old chars to move cursor forwards |
209 | | - stdout_tx_strn(line->buf + cursor_pos, redraw_step_forward); |
210 | | - cursor_pos += redraw_step_forward; |
211 | | - } |
212 | | - |
213 | | - HAL_Delay(1); |
214 | | - } |
215 | | -} |
216 | | - |
217 | 30 | // parses, compiles and executes the code in the lexer |
218 | 31 | // frees the lexer before returning |
219 | 32 | bool parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { |
|
0 commit comments