diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c index 7f63fd2d8e..8909c8be6d 100644 --- a/lib/mp-readline/readline.c +++ b/lib/mp-readline/readline.c @@ -111,12 +111,44 @@ int readline_process_char(int c) { } else if (c == CHAR_CTRL_A) { // CTRL-A with non-empty line is go-to-start-of-line goto home_key; + #if MICROPY_REPL_EMACS_KEYS + } else if (c == CHAR_CTRL_B) { + // CTRL-B with non-empty line is go-back-one-char + goto left_arrow_key; + #endif } else if (c == CHAR_CTRL_C) { // CTRL-C with non-empty line is cancel return c; + #if MICROPY_REPL_EMACS_KEYS + } else if (c == CHAR_CTRL_D) { + // CTRL-D with non-empty line is delete-at-cursor + goto delete_key; + #endif } else if (c == CHAR_CTRL_E) { // CTRL-E is go-to-end-of-line goto end_key; + #if MICROPY_REPL_EMACS_KEYS + } else if (c == CHAR_CTRL_F) { + // CTRL-F with non-empty line is go-forward-one-char + goto right_arrow_key; + } else if (c == CHAR_CTRL_K) { + // CTRL-K is kill from cursor to end-of-line, inclusive + vstr_cut_tail_bytes(rl.line, last_line_len - rl.cursor_pos); + // set redraw parameters + redraw_from_cursor = true; + } else if (c == CHAR_CTRL_N) { + // CTRL-N is go to next line in history + goto down_arrow_key; + } else if (c == CHAR_CTRL_P) { + // CTRL-P is go to previous line in history + goto up_arrow_key; + } else if (c == CHAR_CTRL_U) { + // CTRL-U is kill from beginning-of-line up to cursor + vstr_cut_out_bytes(rl.line, rl.orig_line_len, rl.cursor_pos - rl.orig_line_len); + // set redraw parameters + redraw_step_back = rl.cursor_pos - rl.orig_line_len; + redraw_from_cursor = true; + #endif } else if (c == '\r') { // newline mp_hal_stdout_tx_str("\r\n"); @@ -181,6 +213,9 @@ int readline_process_char(int c) { } else { rl.escape_seq = ESEQ_NONE; if (c == 'A') { +#if MICROPY_REPL_EMACS_KEYS +up_arrow_key: +#endif // up arrow if (rl.hist_cur + 1 < (int)READLINE_HIST_SIZE && MP_STATE_PORT(readline_hist)[rl.hist_cur + 1] != NULL) { // increase hist num @@ -194,6 +229,9 @@ int readline_process_char(int c) { redraw_step_forward = rl.line->len - rl.orig_line_len; } } else if (c == 'B') { +#if MICROPY_REPL_EMACS_KEYS +down_arrow_key: +#endif // down arrow if (rl.hist_cur >= 0) { // decrease hist num @@ -209,11 +247,17 @@ int readline_process_char(int c) { redraw_step_forward = rl.line->len - rl.orig_line_len; } } else if (c == 'C') { +#if MICROPY_REPL_EMACS_KEYS +right_arrow_key: +#endif // right arrow if (rl.cursor_pos < rl.line->len) { redraw_step_forward = 1; } } else if (c == 'D') { +#if MICROPY_REPL_EMACS_KEYS +left_arrow_key: +#endif // left arrow if (rl.cursor_pos > rl.orig_line_len) { redraw_step_back = 1; @@ -238,7 +282,10 @@ end_key: redraw_step_forward = rl.line->len - rl.cursor_pos; } else if (rl.escape_seq_buf[0] == '3') { // delete - if (rl.cursor_pos >= rl.orig_line_len && rl.cursor_pos < rl.line->len) { +#if MICROPY_REPL_EMACS_KEYS +delete_key: +#endif + if (rl.cursor_pos < rl.line->len) { vstr_cut_out_bytes(rl.line, rl.cursor_pos, 1); redraw_from_cursor = true; } diff --git a/lib/mp-readline/readline.h b/lib/mp-readline/readline.h index 6105cea008..f73934d237 100644 --- a/lib/mp-readline/readline.h +++ b/lib/mp-readline/readline.h @@ -29,6 +29,11 @@ #define CHAR_CTRL_C (3) #define CHAR_CTRL_D (4) #define CHAR_CTRL_E (5) +#define CHAR_CTRL_F (6) +#define CHAR_CTRL_K (11) +#define CHAR_CTRL_N (14) +#define CHAR_CTRL_P (16) +#define CHAR_CTRL_U (21) void readline_init0(void); int readline(vstr_t *line, const char *prompt); diff --git a/py/mpconfig.h b/py/mpconfig.h index 9f0e909f53..a345e5fda2 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -303,6 +303,11 @@ #define MICROPY_HELPER_REPL (0) #endif +// Whether to include emacs-style readline behavior in REPL +#ifndef MICROPY_REPL_EMACS_KEYS +#define MICROPY_REPL_EMACS_KEYS (1) +#endif + // Whether port requires event-driven REPL functions #ifndef MICROPY_REPL_EVENT_DRIVEN #define MICROPY_REPL_EVENT_DRIVEN (0) diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 8d6031555c..a6dba431f3 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -39,6 +39,7 @@ #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index 9f65bc9295..a004017797 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -52,6 +52,7 @@ #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_USE_READLINE_HISTORY (1) #define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)