Skip to content

Commit 0af7301

Browse files
committed
lib/mp-readline: Add auto-indent support.
4 spaces are added at start of line to match previous indent, and if previous line ended in colon. Backspace deletes 4 space if only spaces begin a line. Configurable via MICROPY_REPL_AUTO_INDENT. Disabled by default.
1 parent 4e7bde8 commit 0af7301

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

lib/mp-readline/readline.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,29 @@ int readline_process_char(int c) {
160160
} else if (c == 8 || c == 127) {
161161
// backspace/delete
162162
if (rl.cursor_pos > rl.orig_line_len) {
163-
vstr_cut_out_bytes(rl.line, rl.cursor_pos - 1, 1);
163+
// work out how many chars to backspace
164+
#if MICROPY_REPL_AUTO_INDENT
165+
int nspace = 0;
166+
for (size_t i = rl.orig_line_len; i < rl.cursor_pos; i++) {
167+
if (rl.line->buf[i] != ' ') {
168+
nspace = 0;
169+
break;
170+
}
171+
nspace += 1;
172+
}
173+
if (nspace < 4) {
174+
nspace = 1;
175+
} else {
176+
nspace = 4;
177+
}
178+
#else
179+
int nspace = 1;
180+
#endif
181+
182+
// do the backspace
183+
vstr_cut_out_bytes(rl.line, rl.cursor_pos - nspace, nspace);
164184
// set redraw parameters
165-
redraw_step_back = 1;
185+
redraw_step_back = nspace;
166186
redraw_from_cursor = true;
167187
}
168188
#if MICROPY_HELPER_REPL
@@ -335,11 +355,44 @@ int readline_process_char(int c) {
335355
return -1;
336356
}
337357

358+
#if MICROPY_REPL_AUTO_INDENT
359+
STATIC void readline_auto_indent(void) {
360+
vstr_t *line = rl.line;
361+
if (line->len > 1 && line->buf[line->len - 1] == '\n') {
362+
int i;
363+
for (i = line->len - 1; i > 0; i--) {
364+
if (line->buf[i - 1] == '\n') {
365+
break;
366+
}
367+
}
368+
size_t j;
369+
for (j = i; j < line->len; j++) {
370+
if (line->buf[j] != ' ') {
371+
break;
372+
}
373+
}
374+
// i=start of line; j=first non-space
375+
int n = (j - i) / 4;
376+
if (line->buf[line->len - 2] == ':') {
377+
n += 1;
378+
}
379+
while (n-- > 0) {
380+
vstr_add_strn(line, " ", 4);
381+
mp_hal_stdout_tx_strn(" ", 4);
382+
rl.cursor_pos += 4;
383+
}
384+
}
385+
}
386+
#endif
387+
338388
void readline_note_newline(const char *prompt) {
339389
rl.orig_line_len = rl.line->len;
340390
rl.cursor_pos = rl.orig_line_len;
341391
rl.prompt = prompt;
342392
mp_hal_stdout_tx_str(prompt);
393+
#if MICROPY_REPL_AUTO_INDENT
394+
readline_auto_indent();
395+
#endif
343396
}
344397

345398
void readline_init(vstr_t *line, const char *prompt) {
@@ -351,6 +404,9 @@ void readline_init(vstr_t *line, const char *prompt) {
351404
rl.cursor_pos = rl.orig_line_len;
352405
rl.prompt = prompt;
353406
mp_hal_stdout_tx_str(prompt);
407+
#if MICROPY_REPL_AUTO_INDENT
408+
readline_auto_indent();
409+
#endif
354410
}
355411

356412
int readline(vstr_t *line, const char *prompt) {

py/mpconfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@
302302
#define MICROPY_REPL_EMACS_KEYS (0)
303303
#endif
304304

305+
// Whether to implement auto-indent in REPL
306+
#ifndef MICROPY_REPL_AUTO_INDENT
307+
#define MICROPY_REPL_AUTO_INDENT (0)
308+
#endif
309+
305310
// Whether port requires event-driven REPL functions
306311
#ifndef MICROPY_REPL_EVENT_DRIVEN
307312
#define MICROPY_REPL_EVENT_DRIVEN (0)

0 commit comments

Comments
 (0)