Skip to content

Commit f672baa

Browse files
pi-anldpgeorge
authored andcommitted
aiorepl: Add support for raw mode (ctrl-a).
Provides support for mpremote features like cp and mount. Signed-off-by: Andrew Leech <[email protected]>
1 parent 10c9281 commit f672baa

File tree

2 files changed

+90
-7
lines changed

2 files changed

+90
-7
lines changed

micropython/aiorepl/aiorepl.py

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,14 @@ async def task(g=None, prompt="--> "):
160160
else:
161161
cmd = cmd[:-1]
162162
sys.stdout.write("\x08 \x08")
163+
elif c == CHAR_CTRL_A:
164+
await raw_repl(s, g)
165+
break
163166
elif c == CHAR_CTRL_B:
164167
continue
165168
elif c == CHAR_CTRL_C:
166169
if paste:
167170
break
168-
if pc == CHAR_CTRL_C and time.ticks_diff(t, pt) < 20:
169-
# Two very quick Ctrl-C (faster than a human
170-
# typing) likely means mpremote trying to
171-
# escape.
172-
asyncio.new_event_loop()
173-
return
174171
sys.stdout.write("\n")
175172
break
176173
elif c == CHAR_CTRL_D:
@@ -240,3 +237,89 @@ async def task(g=None, prompt="--> "):
240237
cmd += b
241238
finally:
242239
micropython.kbd_intr(3)
240+
241+
242+
async def raw_paste(s, g, window=512):
243+
sys.stdout.write("R\x01") # supported
244+
sys.stdout.write(bytearray([window & 0xFF, window >> 8, 0x01]).decode())
245+
eof = False
246+
idx = 0
247+
buff = bytearray(window)
248+
file = b""
249+
while not eof:
250+
for idx in range(window):
251+
b = await s.read(1)
252+
c = ord(b)
253+
if c == CHAR_CTRL_C or c == CHAR_CTRL_D:
254+
# end of file
255+
sys.stdout.write(chr(CHAR_CTRL_D))
256+
if c == CHAR_CTRL_C:
257+
raise KeyboardInterrupt
258+
file += buff[:idx]
259+
eof = True
260+
break
261+
buff[idx] = c
262+
263+
if not eof:
264+
file += buff
265+
sys.stdout.write("\x01") # indicate window available to host
266+
267+
return file
268+
269+
270+
async def raw_repl(s: asyncio.StreamReader, g: dict):
271+
heading = "raw REPL; CTRL-B to exit\n"
272+
line = ""
273+
sys.stdout.write(heading)
274+
275+
while True:
276+
line = ""
277+
sys.stdout.write(">")
278+
while True:
279+
b = await s.read(1)
280+
c = ord(b)
281+
if c == CHAR_CTRL_A:
282+
rline = line
283+
line = ""
284+
285+
if len(rline) == 2 and ord(rline[0]) == CHAR_CTRL_E:
286+
if rline[1] == "A":
287+
line = await raw_paste(s, g)
288+
break
289+
else:
290+
# reset raw REPL
291+
sys.stdout.write(heading)
292+
sys.stdout.write(">")
293+
continue
294+
elif c == CHAR_CTRL_B:
295+
# exit raw REPL
296+
sys.stdout.write("\n")
297+
return 0
298+
elif c == CHAR_CTRL_C:
299+
# clear line
300+
line = ""
301+
elif c == CHAR_CTRL_D:
302+
# entry finished
303+
# indicate reception of command
304+
sys.stdout.write("OK")
305+
break
306+
else:
307+
# let through any other raw 8-bit value
308+
line += b
309+
310+
if len(line) == 0:
311+
# Normally used to trigger soft-reset but stay in raw mode.
312+
# Fake it for aiorepl / mpremote.
313+
sys.stdout.write("Ignored: soft reboot\n")
314+
sys.stdout.write(heading)
315+
316+
try:
317+
result = exec(line, g)
318+
if result is not None:
319+
sys.stdout.write(repr(result))
320+
sys.stdout.write(chr(CHAR_CTRL_D))
321+
except Exception as ex:
322+
print(line)
323+
sys.stdout.write(chr(CHAR_CTRL_D))
324+
sys.print_exception(ex, sys.stdout)
325+
sys.stdout.write(chr(CHAR_CTRL_D))

micropython/aiorepl/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
metadata(
2-
version="0.1.1",
2+
version="0.2.0",
33
description="Provides an asynchronous REPL that can run concurrently with an asyncio, also allowing await expressions.",
44
)
55

0 commit comments

Comments
 (0)