tools/mpremote: Add repl option to escape non-printable characters.

This commit adds the "--escape-non-printable" option to the repl command.
When specified the REPL console will escape non-printable characters,
printing them as their hex value in square brackets.

This escaping behaviour was previously the default and only behaviour, but
it is now opt-in.

As part of this change, the speed of echoing device data to the console is
improved by by reading and writing in chunks.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2023-05-11 13:24:14 +10:00
parent a802f71908
commit 2771b20d29
3 changed files with 21 additions and 8 deletions

View File

@ -92,6 +92,7 @@ The full list of supported commands are:
Options are: Options are:
- ``--escape-non-printable``, to print non-printable bytes/characters as their hex code
- ``--capture <file>``, to capture output of the REPL session to the given - ``--capture <file>``, to capture output of the REPL session to the given
file file
- ``--inject-code <string>``, to specify characters to inject at the REPL when - ``--inject-code <string>``, to specify characters to inject at the REPL when

View File

@ -119,6 +119,7 @@ def argparse_mount():
def argparse_repl(): def argparse_repl():
cmd_parser = argparse.ArgumentParser(description="connect to given device") cmd_parser = argparse.ArgumentParser(description="connect to given device")
_bool_flag(cmd_parser, "escape-non-printable", "e", False, "escape non-printable characters")
cmd_parser.add_argument( cmd_parser.add_argument(
"--capture", "--capture",
type=str, type=str,

View File

@ -3,7 +3,9 @@ from .console import Console, ConsolePosix
from . import pyboardextended as pyboard from . import pyboardextended as pyboard
def do_repl_main_loop(state, console_in, console_out_write, *, code_to_inject, file_to_inject): def do_repl_main_loop(
state, console_in, console_out_write, *, escape_non_printable, code_to_inject, file_to_inject
):
while True: while True:
console_in.waitchar(state.pyb.serial) console_in.waitchar(state.pyb.serial)
c = console_in.readchar() c = console_in.readchar()
@ -37,26 +39,34 @@ def do_repl_main_loop(state, console_in, console_out_write, *, code_to_inject, f
break break
if n > 0: if n > 0:
c = state.pyb.serial.read(1) dev_data_in = state.pyb.serial.read(n)
if c is not None: if dev_data_in is not None:
# pass character through to the console if escape_non_printable:
oc = ord(c) # Pass data through to the console, with escaping of non-printables.
if oc in (8, 9, 10, 13, 27) or 32 <= oc <= 126: console_data_out = bytearray()
console_out_write(c) for c in dev_data_in:
if c in (8, 9, 10, 13, 27) or 32 <= c <= 126:
console_data_out.append(c)
else:
console_data_out.extend(b"[%02x]" % c)
else: else:
console_out_write(b"[%02x]" % ord(c)) console_data_out = dev_data_in
console_out_write(console_data_out)
def do_repl(state, args): def do_repl(state, args):
state.ensure_friendly_repl() state.ensure_friendly_repl()
state.did_action() state.did_action()
escape_non_printable = args.escape_non_printable
capture_file = args.capture capture_file = args.capture
code_to_inject = args.inject_code code_to_inject = args.inject_code
file_to_inject = args.inject_file file_to_inject = args.inject_file
print("Connected to MicroPython at %s" % state.pyb.device_name) print("Connected to MicroPython at %s" % state.pyb.device_name)
print("Use Ctrl-] or Ctrl-x to exit this shell") print("Use Ctrl-] or Ctrl-x to exit this shell")
if escape_non_printable:
print("Escaping non-printable bytes/characters by printing their hex code")
if capture_file is not None: if capture_file is not None:
print('Capturing session to file "%s"' % capture_file) print('Capturing session to file "%s"' % capture_file)
capture_file = open(capture_file, "wb") capture_file = open(capture_file, "wb")
@ -80,6 +90,7 @@ def do_repl(state, args):
state, state,
console, console,
console_out_write, console_out_write,
escape_non_printable=escape_non_printable,
code_to_inject=code_to_inject, code_to_inject=code_to_inject,
file_to_inject=file_to_inject, file_to_inject=file_to_inject,
) )