Skip to content

Commit 2af6012

Browse files
committed
micropython/aiorepl: Add support for raw mode (ctrl-a).
Provides support for mpremote features like cp and mount.
1 parent 3a688ad commit 2af6012

File tree

1 file changed

+89
-6
lines changed

1 file changed

+89
-6
lines changed

micropython/aiorepl/aiorepl.py

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

0 commit comments

Comments
 (0)