summaryrefslogtreecommitdiff
path: root/shared/readline/readline.c
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-03-08 11:11:23 +1100
committerDamien George <damien@micropython.org>2022-04-22 17:00:16 +1000
commit6d401be4dd0164cb197a05c7419f7b6ef5bbdf51 (patch)
tree1f7ce1e103a5072a0800aacaf3e791289ad151d3 /shared/readline/readline.c
parenta8f23f6366b7bb258c7c34a45a3a9bde99e4a32b (diff)
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 #7925. Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'shared/readline/readline.c')
-rw-r--r--shared/readline/readline.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/shared/readline/readline.c b/shared/readline/readline.c
index 915bcda84..9b8961712 100644
--- a/shared/readline/readline.c
+++ b/shared/readline/readline.c
@@ -42,6 +42,10 @@
#define READLINE_HIST_SIZE (MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist)))
+// flags for readline_t.auto_indent_state
+#define AUTO_INDENT_ENABLED (0x01)
+#define AUTO_INDENT_JUST_ADDED (0x02)
+
enum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O };
void readline_init0(void) {
@@ -94,6 +98,9 @@ typedef struct _readline_t {
int hist_cur;
size_t cursor_pos;
char escape_seq_buf[1];
+ #if MICROPY_REPL_AUTO_INDENT
+ uint8_t auto_indent_state;
+ #endif
const char *prompt;
} readline_t;
@@ -218,6 +225,17 @@ int readline_process_char(int c) {
redraw_step_back = nspace;
redraw_from_cursor = true;
}
+ #if MICROPY_REPL_AUTO_INDENT
+ } else if ((rl.auto_indent_state & AUTO_INDENT_JUST_ADDED) && (c == 9 || c == ' ')) {
+ // tab/space after auto-indent: disable auto-indent
+ // - if it's a tab then leave existing indent
+ // - if it's a space then remove 3 spaces from existing indent
+ rl.auto_indent_state = 0;
+ if (c == ' ') {
+ redraw_step_back = 3;
+ vstr_cut_tail_bytes(rl.line, 3);
+ }
+ #endif
#if MICROPY_HELPER_REPL
} else if (c == 9) {
// tab magic
@@ -452,11 +470,18 @@ redraw:
rl.cursor_pos += redraw_step_forward;
}
+ #if MICROPY_REPL_AUTO_INDENT
+ rl.auto_indent_state &= ~AUTO_INDENT_JUST_ADDED;
+ #endif
+
return -1;
}
#if MICROPY_REPL_AUTO_INDENT
STATIC void readline_auto_indent(void) {
+ if (!(rl.auto_indent_state & AUTO_INDENT_ENABLED)) {
+ return;
+ }
vstr_t *line = rl.line;
if (line->len > 1 && line->buf[line->len - 1] == '\n') {
int i;
@@ -492,6 +517,7 @@ STATIC void readline_auto_indent(void) {
vstr_add_strn(line, " ", 4);
mp_hal_stdout_tx_strn(" ", 4);
rl.cursor_pos += 4;
+ rl.auto_indent_state |= AUTO_INDENT_JUST_ADDED;
}
}
}
@@ -517,6 +543,10 @@ void readline_init(vstr_t *line, const char *prompt) {
rl.prompt = prompt;
mp_hal_stdout_tx_str(prompt);
#if MICROPY_REPL_AUTO_INDENT
+ if (vstr_len(line) == 0) {
+ // start with auto-indent enabled
+ rl.auto_indent_state = AUTO_INDENT_ENABLED;
+ }
readline_auto_indent();
#endif
}