Commit 46a11028 authored by Damien George's avatar Damien George
Browse files

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.
parent 1b586f3a
...@@ -105,7 +105,7 @@ int readline_process_char(int c) { ...@@ -105,7 +105,7 @@ int readline_process_char(int c) {
bool redraw_from_cursor = false; bool redraw_from_cursor = false;
int redraw_step_forward = 0; int redraw_step_forward = 0;
if (rl.escape_seq == ESEQ_NONE) { 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 // control character with empty line
return c; return c;
} else if (c == CHAR_CTRL_A) { } else if (c == CHAR_CTRL_A) {
......
...@@ -389,6 +389,7 @@ friendly_repl_reset: ...@@ -389,6 +389,7 @@ friendly_repl_reset:
vstr_reset(&line); vstr_reset(&line);
int ret = readline(&line, ">>> "); int ret = readline(&line, ">>> ");
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
if (ret == CHAR_CTRL_A) { if (ret == CHAR_CTRL_A) {
// change to raw REPL // change to raw REPL
...@@ -409,20 +410,46 @@ friendly_repl_reset: ...@@ -409,20 +410,46 @@ friendly_repl_reset:
mp_hal_stdout_tx_str("\r\n"); mp_hal_stdout_tx_str("\r\n");
vstr_clear(&line); vstr_clear(&line);
return PYEXEC_FORCED_EXIT; 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) { } else if (vstr_len(&line) == 0) {
continue; continue;
} } else {
// got a line with non-zero length, see if it needs continuing
while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
vstr_add_byte(&line, '\n'); vstr_add_byte(&line, '\n');
ret = readline(&line, "... "); ret = readline(&line, "... ");
if (ret == CHAR_CTRL_C) { if (ret == CHAR_CTRL_C) {
// cancel everything // cancel everything
mp_hal_stdout_tx_str("\r\n"); mp_hal_stdout_tx_str("\r\n");
goto input_restart; goto input_restart;
} else if (ret == CHAR_CTRL_D) { } else if (ret == CHAR_CTRL_D) {
// stop entering compound statement // stop entering compound statement
break; break;
}
} }
} }
...@@ -430,7 +457,7 @@ friendly_repl_reset: ...@@ -430,7 +457,7 @@ friendly_repl_reset:
if (lex == NULL) { if (lex == NULL) {
printf("MemoryError\n"); printf("MemoryError\n");
} else { } 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) { if (ret & PYEXEC_FORCED_EXIT) {
return ret; return ret;
} }
......
...@@ -162,10 +162,12 @@ STATIC int do_repl(void) { ...@@ -162,10 +162,12 @@ STATIC int do_repl(void) {
vstr_t line; vstr_t line;
vstr_init(&line, 16); vstr_init(&line, 16);
for (;;) { for (;;) {
mp_hal_stdio_mode_raw();
input_restart: input_restart:
vstr_reset(&line); vstr_reset(&line);
mp_hal_stdio_mode_raw();
int ret = readline(&line, ">>> "); int ret = readline(&line, ">>> ");
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
if (ret == CHAR_CTRL_D) { if (ret == CHAR_CTRL_D) {
// EOF // EOF
...@@ -173,31 +175,56 @@ STATIC int do_repl(void) { ...@@ -173,31 +175,56 @@ STATIC int do_repl(void) {
mp_hal_stdio_mode_orig(); mp_hal_stdio_mode_orig();
vstr_clear(&line); vstr_clear(&line);
return 0; 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) { } else if (line.len == 0) {
if (ret != 0) { if (ret != 0) {
printf("\n"); printf("\n");
} }
mp_hal_stdio_mode_orig(); goto input_restart;
continue; } else {
} // got a line with non-zero length, see if it needs continuing
while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { vstr_add_byte(&line, '\n');
vstr_add_byte(&line, '\n'); ret = readline(&line, "... ");
ret = readline(&line, "... "); if (ret == CHAR_CTRL_C) {
if (ret == CHAR_CTRL_C) { // cancel everything
// cancel everything printf("\n");
printf("\n"); goto input_restart;
mp_hal_stdio_mode_orig(); } else if (ret == CHAR_CTRL_D) {
goto input_restart; // stop entering compound statement
} else if (ret == CHAR_CTRL_D) { break;
// stop entering compound statement }
break;
} }
} }
mp_hal_stdio_mode_orig(); 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); 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) { if (ret & FORCED_EXIT) {
return ret; return ret;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment