Skip to content

Commit 6d401be

Browse files
committed
shared/readline: Disable auto-indent if space/tab follows added indent.
Auto-indent still works as the default behaviour, but it is now undone and disabled if there is a space/tab immediately after an automatically-added indent. This makes the REPL behaviour closer to CPython, and in particular allows text to be pasted at the normal REPL. Addresses issue adafruit#7925. Signed-off-by: Damien George <damien@micropython.org>
1 parent a8f23f6 commit 6d401be

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

shared/readline/readline.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242

4343
#define READLINE_HIST_SIZE (MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist)))
4444

45+
// flags for readline_t.auto_indent_state
46+
#define AUTO_INDENT_ENABLED (0x01)
47+
#define AUTO_INDENT_JUST_ADDED (0x02)
48+
4549
enum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O };
4650

4751
void readline_init0(void) {
@@ -94,6 +98,9 @@ typedef struct _readline_t {
9498
int hist_cur;
9599
size_t cursor_pos;
96100
char escape_seq_buf[1];
101+
#if MICROPY_REPL_AUTO_INDENT
102+
uint8_t auto_indent_state;
103+
#endif
97104
const char *prompt;
98105
} readline_t;
99106

@@ -218,6 +225,17 @@ int readline_process_char(int c) {
218225
redraw_step_back = nspace;
219226
redraw_from_cursor = true;
220227
}
228+
#if MICROPY_REPL_AUTO_INDENT
229+
} else if ((rl.auto_indent_state & AUTO_INDENT_JUST_ADDED) && (c == 9 || c == ' ')) {
230+
// tab/space after auto-indent: disable auto-indent
231+
// - if it's a tab then leave existing indent
232+
// - if it's a space then remove 3 spaces from existing indent
233+
rl.auto_indent_state = 0;
234+
if (c == ' ') {
235+
redraw_step_back = 3;
236+
vstr_cut_tail_bytes(rl.line, 3);
237+
}
238+
#endif
221239
#if MICROPY_HELPER_REPL
222240
} else if (c == 9) {
223241
// tab magic
@@ -452,11 +470,18 @@ int readline_process_char(int c) {
452470
rl.cursor_pos += redraw_step_forward;
453471
}
454472

473+
#if MICROPY_REPL_AUTO_INDENT
474+
rl.auto_indent_state &= ~AUTO_INDENT_JUST_ADDED;
475+
#endif
476+
455477
return -1;
456478
}
457479

458480
#if MICROPY_REPL_AUTO_INDENT
459481
STATIC void readline_auto_indent(void) {
482+
if (!(rl.auto_indent_state & AUTO_INDENT_ENABLED)) {
483+
return;
484+
}
460485
vstr_t *line = rl.line;
461486
if (line->len > 1 && line->buf[line->len - 1] == '\n') {
462487
int i;
@@ -492,6 +517,7 @@ STATIC void readline_auto_indent(void) {
492517
vstr_add_strn(line, " ", 4);
493518
mp_hal_stdout_tx_strn(" ", 4);
494519
rl.cursor_pos += 4;
520+
rl.auto_indent_state |= AUTO_INDENT_JUST_ADDED;
495521
}
496522
}
497523
}
@@ -517,6 +543,10 @@ void readline_init(vstr_t *line, const char *prompt) {
517543
rl.prompt = prompt;
518544
mp_hal_stdout_tx_str(prompt);
519545
#if MICROPY_REPL_AUTO_INDENT
546+
if (vstr_len(line) == 0) {
547+
// start with auto-indent enabled
548+
rl.auto_indent_state = AUTO_INDENT_ENABLED;
549+
}
520550
readline_auto_indent();
521551
#endif
522552
}

0 commit comments

Comments
 (0)