summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2015-10-09 22:41:10 +0100
committerDamien George <damien.p.george@gmail.com>2015-10-11 23:30:22 +0100
commit46a11028521425e7d6c85458c849bb96ff82152e (patch)
treec13f48bea9f947bc4c3e1cda04adc7d5437e8edf
parent1b586f3a734c27c78080fb2173bbde17168cb9e4 (diff)
downloadmicropython-46a11028521425e7d6c85458c849bb96ff82152e.tar.gz
micropython-46a11028521425e7d6c85458c849bb96ff82152e.zip
repl: Add paste mode to friendly REPL, entered via CTRL-E.
Use CTRL-E to enter paste mode. Prompt starts with "===" and accepts all characters verbatim, echoing them back. Only control characters are CTRL-C which cancels the input and returns to normal REPL, and CTRL-D which ends the input and executes it. The input is executed as though it were a file. The input is not added to the prompt history.
-rw-r--r--lib/mp-readline/readline.c2
-rw-r--r--stmhal/pyexec.c53
-rw-r--r--unix/main.c61
3 files changed, 85 insertions, 31 deletions
diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c
index d0449e97ea..31b60e2682 100644
--- a/lib/mp-readline/readline.c
+++ b/lib/mp-readline/readline.c
@@ -105,7 +105,7 @@ int readline_process_char(int c) {
bool redraw_from_cursor = false;
int redraw_step_forward = 0;
if (rl.escape_seq == ESEQ_NONE) {
- if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_D && vstr_len(rl.line) == rl.orig_line_len) {
+ if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_E && vstr_len(rl.line) == rl.orig_line_len) {
// control character with empty line
return c;
} else if (c == CHAR_CTRL_A) {
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index c692933dc0..a809940a8a 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -389,6 +389,7 @@ friendly_repl_reset:
vstr_reset(&line);
int ret = readline(&line, ">>> ");
+ mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
if (ret == CHAR_CTRL_A) {
// change to raw REPL
@@ -409,20 +410,46 @@ friendly_repl_reset:
mp_hal_stdout_tx_str("\r\n");
vstr_clear(&line);
return PYEXEC_FORCED_EXIT;
+ } else if (ret == CHAR_CTRL_E) {
+ // paste mode
+ mp_hal_stdout_tx_str("\r\npaste mode; CTRL-C to cancel, CTRL-D to finish\r\n=== ");
+ vstr_reset(&line);
+ for (;;) {
+ char c = mp_hal_stdin_rx_chr();
+ if (c == CHAR_CTRL_C) {
+ // cancel everything
+ mp_hal_stdout_tx_str("\r\n");
+ goto input_restart;
+ } else if (c == CHAR_CTRL_D) {
+ // end of input
+ mp_hal_stdout_tx_str("\r\n");
+ break;
+ } else {
+ // add char to buffer and echo
+ vstr_add_byte(&line, c);
+ if (c == '\r') {
+ mp_hal_stdout_tx_str("\r\n=== ");
+ } else {
+ mp_hal_stdout_tx_strn(&c, 1);
+ }
+ }
+ }
+ parse_input_kind = MP_PARSE_FILE_INPUT;
} else if (vstr_len(&line) == 0) {
continue;
- }
-
- while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
- vstr_add_byte(&line, '\n');
- ret = readline(&line, "... ");
- if (ret == CHAR_CTRL_C) {
- // cancel everything
- mp_hal_stdout_tx_str("\r\n");
- goto input_restart;
- } else if (ret == CHAR_CTRL_D) {
- // stop entering compound statement
- break;
+ } else {
+ // got a line with non-zero length, see if it needs continuing
+ while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
+ vstr_add_byte(&line, '\n');
+ ret = readline(&line, "... ");
+ if (ret == CHAR_CTRL_C) {
+ // cancel everything
+ mp_hal_stdout_tx_str("\r\n");
+ goto input_restart;
+ } else if (ret == CHAR_CTRL_D) {
+ // stop entering compound statement
+ break;
+ }
}
}
@@ -430,7 +457,7 @@ friendly_repl_reset:
if (lex == NULL) {
printf("MemoryError\n");
} else {
- ret = parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL);
+ ret = parse_compile_execute(lex, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL);
if (ret & PYEXEC_FORCED_EXIT) {
return ret;
}
diff --git a/unix/main.c b/unix/main.c
index 7a2f7e4ff1..a3f4cfe6cf 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -162,10 +162,12 @@ STATIC int do_repl(void) {
vstr_t line;
vstr_init(&line, 16);
for (;;) {
+ mp_hal_stdio_mode_raw();
+
input_restart:
vstr_reset(&line);
- mp_hal_stdio_mode_raw();
int ret = readline(&line, ">>> ");
+ mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
if (ret == CHAR_CTRL_D) {
// EOF
@@ -173,31 +175,56 @@ STATIC int do_repl(void) {
mp_hal_stdio_mode_orig();
vstr_clear(&line);
return 0;
+ } else if (ret == CHAR_CTRL_E) {
+ // paste mode
+ mp_hal_stdout_tx_str("\npaste mode; CTRL-C to cancel, CTRL-D to finish\n=== ");
+ vstr_reset(&line);
+ for (;;) {
+ char c = mp_hal_stdin_rx_chr();
+ if (c == CHAR_CTRL_C) {
+ // cancel everything
+ mp_hal_stdout_tx_str("\n");
+ goto input_restart;
+ } else if (c == CHAR_CTRL_D) {
+ // end of input
+ mp_hal_stdout_tx_str("\n");
+ break;
+ } else {
+ // add char to buffer and echo
+ vstr_add_byte(&line, c);
+ if (c == '\r') {
+ mp_hal_stdout_tx_str("\n=== ");
+ } else {
+ mp_hal_stdout_tx_strn(&c, 1);
+ }
+ }
+ }
+ parse_input_kind = MP_PARSE_FILE_INPUT;
} else if (line.len == 0) {
if (ret != 0) {
printf("\n");
}
- mp_hal_stdio_mode_orig();
- continue;
- }
-
- while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
- vstr_add_byte(&line, '\n');
- ret = readline(&line, "... ");
- if (ret == CHAR_CTRL_C) {
- // cancel everything
- printf("\n");
- mp_hal_stdio_mode_orig();
- goto input_restart;
- } else if (ret == CHAR_CTRL_D) {
- // stop entering compound statement
- break;
+ goto input_restart;
+ } else {
+ // got a line with non-zero length, see if it needs continuing
+ while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
+ vstr_add_byte(&line, '\n');
+ ret = readline(&line, "... ");
+ if (ret == CHAR_CTRL_C) {
+ // cancel everything
+ printf("\n");
+ goto input_restart;
+ } else if (ret == CHAR_CTRL_D) {
+ // stop entering compound statement
+ break;
+ }
}
}
+
mp_hal_stdio_mode_orig();
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, false);
- ret = execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, true);
+ ret = execute_from_lexer(lex, parse_input_kind, true);
if (ret & FORCED_EXIT) {
return ret;
}