kopia lustrzana https://github.com/micropython/micropython-lib
Merge e156b6fedc
into 96bd01ec04
commit
a181cfdf65
|
@ -93,13 +93,13 @@ __exec_task = asyncio.create_task(__code())
|
||||||
|
|
||||||
|
|
||||||
# REPL task. Invoke this with an optional mutable globals dict.
|
# REPL task. Invoke this with an optional mutable globals dict.
|
||||||
async def task(g=None, prompt="--> "):
|
async def task(g=None, prompt="--> ", s_in=sys.stdin, s_out=sys.stdout):
|
||||||
print("Starting asyncio REPL...")
|
print("Starting asyncio REPL...")
|
||||||
if g is None:
|
if g is None:
|
||||||
g = __import__("__main__").__dict__
|
g = __import__("__main__").__dict__
|
||||||
try:
|
try:
|
||||||
micropython.kbd_intr(-1)
|
micropython.kbd_intr(-1)
|
||||||
s = asyncio.StreamReader(sys.stdin)
|
s = asyncio.StreamReader(s_in)
|
||||||
# clear = True
|
# clear = True
|
||||||
hist = [None] * _HISTORY_LIMIT
|
hist = [None] * _HISTORY_LIMIT
|
||||||
hist_i = 0 # Index of most recent entry.
|
hist_i = 0 # Index of most recent entry.
|
||||||
|
@ -108,7 +108,7 @@ async def task(g=None, prompt="--> "):
|
||||||
t = 0 # timestamp of most recent character.
|
t = 0 # timestamp of most recent character.
|
||||||
while True:
|
while True:
|
||||||
hist_b = 0 # How far back in the history are we currently.
|
hist_b = 0 # How far back in the history are we currently.
|
||||||
sys.stdout.write(prompt)
|
s_out.write(prompt)
|
||||||
cmd: str = ""
|
cmd: str = ""
|
||||||
paste = False
|
paste = False
|
||||||
curs = 0 # cursor offset from end of cmd buffer
|
curs = 0 # cursor offset from end of cmd buffer
|
||||||
|
@ -122,7 +122,7 @@ async def task(g=None, prompt="--> "):
|
||||||
if c == 0x0A:
|
if c == 0x0A:
|
||||||
# LF
|
# LF
|
||||||
if paste:
|
if paste:
|
||||||
sys.stdout.write(b)
|
s_out.write(b)
|
||||||
cmd += b
|
cmd += b
|
||||||
continue
|
continue
|
||||||
# If the previous character was also LF, and was less
|
# If the previous character was also LF, and was less
|
||||||
|
@ -132,9 +132,9 @@ async def task(g=None, prompt="--> "):
|
||||||
continue
|
continue
|
||||||
if curs:
|
if curs:
|
||||||
# move cursor to end of the line
|
# move cursor to end of the line
|
||||||
sys.stdout.write("\x1b[{}C".format(curs))
|
s_out.write("\x1b[{}C".format(curs))
|
||||||
curs = 0
|
curs = 0
|
||||||
sys.stdout.write("\n")
|
s_out.write("\n")
|
||||||
if cmd:
|
if cmd:
|
||||||
# Push current command.
|
# Push current command.
|
||||||
hist[hist_i] = cmd
|
hist[hist_i] = cmd
|
||||||
|
@ -144,46 +144,46 @@ async def task(g=None, prompt="--> "):
|
||||||
|
|
||||||
result = await execute(cmd, g, s)
|
result = await execute(cmd, g, s)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
sys.stdout.write(repr(result))
|
s_out.write(repr(result))
|
||||||
sys.stdout.write("\n")
|
s_out.write("\n")
|
||||||
break
|
break
|
||||||
elif c == 0x08 or c == 0x7F:
|
elif c == 0x08 or c == 0x7F:
|
||||||
# Backspace.
|
# Backspace.
|
||||||
if cmd:
|
if cmd:
|
||||||
if curs:
|
if curs:
|
||||||
cmd = "".join((cmd[: -curs - 1], cmd[-curs:]))
|
cmd = "".join((cmd[: -curs - 1], cmd[-curs:]))
|
||||||
sys.stdout.write(
|
s_out.write(
|
||||||
"\x08\x1b[K"
|
"\x08\x1b[K"
|
||||||
) # move cursor back, erase to end of line
|
) # move cursor back, erase to end of line
|
||||||
sys.stdout.write(cmd[-curs:]) # redraw line
|
s_out.write(cmd[-curs:]) # redraw line
|
||||||
sys.stdout.write("\x1b[{}D".format(curs)) # reset cursor location
|
s_out.write("\x1b[{}D".format(curs)) # reset cursor location
|
||||||
else:
|
else:
|
||||||
cmd = cmd[:-1]
|
cmd = cmd[:-1]
|
||||||
sys.stdout.write("\x08 \x08")
|
s_out.write("\x08 \x08")
|
||||||
elif c == CHAR_CTRL_A:
|
elif c == CHAR_CTRL_A:
|
||||||
await raw_repl(s, g)
|
await raw_repl(s_in, s_out, g)
|
||||||
break
|
break
|
||||||
elif c == CHAR_CTRL_B:
|
elif c == CHAR_CTRL_B:
|
||||||
continue
|
continue
|
||||||
elif c == CHAR_CTRL_C:
|
elif c == CHAR_CTRL_C:
|
||||||
if paste:
|
if paste:
|
||||||
break
|
break
|
||||||
sys.stdout.write("\n")
|
s_out.write("\n")
|
||||||
break
|
break
|
||||||
elif c == CHAR_CTRL_D:
|
elif c == CHAR_CTRL_D:
|
||||||
if paste:
|
if paste:
|
||||||
result = await execute(cmd, g, s)
|
result = await execute(cmd, g, s)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
sys.stdout.write(repr(result))
|
s_out.write(repr(result))
|
||||||
sys.stdout.write("\n")
|
s_out.write("\n")
|
||||||
break
|
break
|
||||||
|
|
||||||
sys.stdout.write("\n")
|
s_out.write("\n")
|
||||||
# Shutdown asyncio.
|
# Shutdown asyncio.
|
||||||
asyncio.new_event_loop()
|
asyncio.new_event_loop()
|
||||||
return
|
return
|
||||||
elif c == CHAR_CTRL_E:
|
elif c == CHAR_CTRL_E:
|
||||||
sys.stdout.write("paste mode; Ctrl-C to cancel, Ctrl-D to finish\n===\n")
|
s_out.write("paste mode; Ctrl-C to cancel, Ctrl-D to finish\n===\n")
|
||||||
paste = True
|
paste = True
|
||||||
elif c == 0x1B:
|
elif c == 0x1B:
|
||||||
# Start of escape sequence.
|
# Start of escape sequence.
|
||||||
|
@ -193,9 +193,9 @@ async def task(g=None, prompt="--> "):
|
||||||
hist[(hist_i - hist_b) % _HISTORY_LIMIT] = cmd
|
hist[(hist_i - hist_b) % _HISTORY_LIMIT] = cmd
|
||||||
# Clear current command.
|
# Clear current command.
|
||||||
b = "\x08" * len(cmd)
|
b = "\x08" * len(cmd)
|
||||||
sys.stdout.write(b)
|
s_out.write(b)
|
||||||
sys.stdout.write(" " * len(cmd))
|
s_out.write(" " * len(cmd))
|
||||||
sys.stdout.write(b)
|
s_out.write(b)
|
||||||
# Go backwards or forwards in the history.
|
# Go backwards or forwards in the history.
|
||||||
if key == "[A":
|
if key == "[A":
|
||||||
hist_b = min(hist_n, hist_b + 1)
|
hist_b = min(hist_n, hist_b + 1)
|
||||||
|
@ -203,56 +203,56 @@ async def task(g=None, prompt="--> "):
|
||||||
hist_b = max(0, hist_b - 1)
|
hist_b = max(0, hist_b - 1)
|
||||||
# Update current command.
|
# Update current command.
|
||||||
cmd = hist[(hist_i - hist_b) % _HISTORY_LIMIT]
|
cmd = hist[(hist_i - hist_b) % _HISTORY_LIMIT]
|
||||||
sys.stdout.write(cmd)
|
s_out.write(cmd)
|
||||||
elif key == "[D": # left
|
elif key == "[D": # left
|
||||||
if curs < len(cmd) - 1:
|
if curs < len(cmd) - 1:
|
||||||
curs += 1
|
curs += 1
|
||||||
sys.stdout.write("\x1b")
|
s_out.write("\x1b")
|
||||||
sys.stdout.write(key)
|
s_out.write(key)
|
||||||
elif key == "[C": # right
|
elif key == "[C": # right
|
||||||
if curs:
|
if curs:
|
||||||
curs -= 1
|
curs -= 1
|
||||||
sys.stdout.write("\x1b")
|
s_out.write("\x1b")
|
||||||
sys.stdout.write(key)
|
s_out.write(key)
|
||||||
elif key == "[H": # home
|
elif key == "[H": # home
|
||||||
pcurs = curs
|
pcurs = curs
|
||||||
curs = len(cmd)
|
curs = len(cmd)
|
||||||
sys.stdout.write("\x1b[{}D".format(curs - pcurs)) # move cursor left
|
s_out.write("\x1b[{}D".format(curs - pcurs)) # move cursor left
|
||||||
elif key == "[F": # end
|
elif key == "[F": # end
|
||||||
pcurs = curs
|
pcurs = curs
|
||||||
curs = 0
|
curs = 0
|
||||||
sys.stdout.write("\x1b[{}C".format(pcurs)) # move cursor right
|
s_out.write("\x1b[{}C".format(pcurs)) # move cursor right
|
||||||
else:
|
else:
|
||||||
# sys.stdout.write("\\x")
|
# s_out.write("\\x")
|
||||||
# sys.stdout.write(hex(c))
|
# s_out.write(hex(c))
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if curs:
|
if curs:
|
||||||
# inserting into middle of line
|
# inserting into middle of line
|
||||||
cmd = "".join((cmd[:-curs], b, cmd[-curs:]))
|
cmd = "".join((cmd[:-curs], b, cmd[-curs:]))
|
||||||
sys.stdout.write(cmd[-curs - 1 :]) # redraw line to end
|
s_out.write(cmd[-curs - 1 :]) # redraw line to end
|
||||||
sys.stdout.write("\x1b[{}D".format(curs)) # reset cursor location
|
s_out.write("\x1b[{}D".format(curs)) # reset cursor location
|
||||||
else:
|
else:
|
||||||
sys.stdout.write(b)
|
s_out.write(b)
|
||||||
cmd += b
|
cmd += b
|
||||||
finally:
|
finally:
|
||||||
micropython.kbd_intr(3)
|
micropython.kbd_intr(3)
|
||||||
|
|
||||||
|
|
||||||
async def raw_paste(s, g, window=512):
|
def raw_paste(s_in, s_out, window=512):
|
||||||
sys.stdout.write("R\x01") # supported
|
s_out.write("R\x01") # supported
|
||||||
sys.stdout.write(bytearray([window & 0xFF, window >> 8, 0x01]).decode())
|
s_out.write(bytearray([window & 0xFF, window >> 8, 0x01]).decode())
|
||||||
eof = False
|
eof = False
|
||||||
idx = 0
|
idx = 0
|
||||||
buff = bytearray(window)
|
buff = bytearray(window)
|
||||||
file = b""
|
file = b""
|
||||||
while not eof:
|
while not eof:
|
||||||
for idx in range(window):
|
for idx in range(window):
|
||||||
b = await s.read(1)
|
b = s_in.read(1)
|
||||||
c = ord(b)
|
c = ord(b)
|
||||||
if c == CHAR_CTRL_C or c == CHAR_CTRL_D:
|
if c == CHAR_CTRL_C or c == CHAR_CTRL_D:
|
||||||
# end of file
|
# end of file
|
||||||
sys.stdout.write(chr(CHAR_CTRL_D))
|
s_out.write(chr(CHAR_CTRL_D))
|
||||||
if c == CHAR_CTRL_C:
|
if c == CHAR_CTRL_C:
|
||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
file += buff[:idx]
|
file += buff[:idx]
|
||||||
|
@ -262,21 +262,26 @@ async def raw_paste(s, g, window=512):
|
||||||
|
|
||||||
if not eof:
|
if not eof:
|
||||||
file += buff
|
file += buff
|
||||||
sys.stdout.write("\x01") # indicate window available to host
|
s_out.write("\x01") # indicate window available to host
|
||||||
|
|
||||||
return file
|
return file
|
||||||
|
|
||||||
|
|
||||||
async def raw_repl(s: asyncio.StreamReader, g: dict):
|
async def raw_repl(s_in: io.IOBase, s_out: io.IOBase, g: dict):
|
||||||
|
"""
|
||||||
|
This function is blocking to prevent other
|
||||||
|
async tasks from writing to the stdio stream and
|
||||||
|
breaking the raw repl session.
|
||||||
|
"""
|
||||||
heading = "raw REPL; CTRL-B to exit\n"
|
heading = "raw REPL; CTRL-B to exit\n"
|
||||||
line = ""
|
line = ""
|
||||||
sys.stdout.write(heading)
|
s_out.write(heading)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
line = ""
|
line = ""
|
||||||
sys.stdout.write(">")
|
s_out.write(">")
|
||||||
while True:
|
while True:
|
||||||
b = await s.read(1)
|
b = s_in.read(1)
|
||||||
c = ord(b)
|
c = ord(b)
|
||||||
if c == CHAR_CTRL_A:
|
if c == CHAR_CTRL_A:
|
||||||
rline = line
|
rline = line
|
||||||
|
@ -284,16 +289,16 @@ async def raw_repl(s: asyncio.StreamReader, g: dict):
|
||||||
|
|
||||||
if len(rline) == 2 and ord(rline[0]) == CHAR_CTRL_E:
|
if len(rline) == 2 and ord(rline[0]) == CHAR_CTRL_E:
|
||||||
if rline[1] == "A":
|
if rline[1] == "A":
|
||||||
line = await raw_paste(s, g)
|
line = raw_paste(s_in, s_out)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# reset raw REPL
|
# reset raw REPL
|
||||||
sys.stdout.write(heading)
|
s_out.write(heading)
|
||||||
sys.stdout.write(">")
|
s_out.write(">")
|
||||||
continue
|
continue
|
||||||
elif c == CHAR_CTRL_B:
|
elif c == CHAR_CTRL_B:
|
||||||
# exit raw REPL
|
# exit raw REPL
|
||||||
sys.stdout.write("\n")
|
s_out.write("\n")
|
||||||
return 0
|
return 0
|
||||||
elif c == CHAR_CTRL_C:
|
elif c == CHAR_CTRL_C:
|
||||||
# clear line
|
# clear line
|
||||||
|
@ -301,7 +306,7 @@ async def raw_repl(s: asyncio.StreamReader, g: dict):
|
||||||
elif c == CHAR_CTRL_D:
|
elif c == CHAR_CTRL_D:
|
||||||
# entry finished
|
# entry finished
|
||||||
# indicate reception of command
|
# indicate reception of command
|
||||||
sys.stdout.write("OK")
|
s_out.write("OK")
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# let through any other raw 8-bit value
|
# let through any other raw 8-bit value
|
||||||
|
@ -310,16 +315,16 @@ async def raw_repl(s: asyncio.StreamReader, g: dict):
|
||||||
if len(line) == 0:
|
if len(line) == 0:
|
||||||
# Normally used to trigger soft-reset but stay in raw mode.
|
# Normally used to trigger soft-reset but stay in raw mode.
|
||||||
# Fake it for aiorepl / mpremote.
|
# Fake it for aiorepl / mpremote.
|
||||||
sys.stdout.write("Ignored: soft reboot\n")
|
s_out.write("Ignored: soft reboot\n")
|
||||||
sys.stdout.write(heading)
|
s_out.write(heading)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = exec(line, g)
|
result = exec(line, g)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
sys.stdout.write(repr(result))
|
s_out.write(repr(result))
|
||||||
sys.stdout.write(chr(CHAR_CTRL_D))
|
s_out.write(chr(CHAR_CTRL_D))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print(line)
|
print(line)
|
||||||
sys.stdout.write(chr(CHAR_CTRL_D))
|
s_out.write(chr(CHAR_CTRL_D))
|
||||||
sys.print_exception(ex, sys.stdout)
|
sys.print_exception(ex, s_out)
|
||||||
sys.stdout.write(chr(CHAR_CTRL_D))
|
s_out.write(chr(CHAR_CTRL_D))
|
||||||
|
|
Ładowanie…
Reference in New Issue