aiorepl: Add cursor left/right support.

Allows modifying current line, adding/deleting characters in the middle
etc.  Includes home/end keys to move to start/end of current line.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
pull/756/head
Andrew Leech 2023-10-24 15:36:53 +11:00 zatwierdzone przez Damien George
rodzic d41851ca72
commit 10c9281dad
1 zmienionych plików z 42 dodań i 5 usunięć

Wyświetl plik

@ -111,6 +111,7 @@ async def task(g=None, prompt="--> "):
sys.stdout.write(prompt) sys.stdout.write(prompt)
cmd: str = "" cmd: str = ""
paste = False paste = False
curs = 0 # cursor offset from end of cmd buffer
while True: while True:
b = await s.read(1) b = await s.read(1)
pc = c # save previous character pc = c # save previous character
@ -129,6 +130,10 @@ async def task(g=None, prompt="--> "):
# conversion, so ignore this linefeed. # conversion, so ignore this linefeed.
if pc == 0x0A and time.ticks_diff(t, pt) < 20: if pc == 0x0A and time.ticks_diff(t, pt) < 20:
continue continue
if curs:
# move cursor to end of the line
sys.stdout.write("\x1B[{}C".format(curs))
curs = 0
sys.stdout.write("\n") sys.stdout.write("\n")
if cmd: if cmd:
# Push current command. # Push current command.
@ -145,8 +150,16 @@ async def task(g=None, prompt="--> "):
elif c == 0x08 or c == 0x7F: elif c == 0x08 or c == 0x7F:
# Backspace. # Backspace.
if cmd: if cmd:
cmd = cmd[:-1] if curs:
sys.stdout.write("\x08 \x08") cmd = "".join((cmd[: -curs - 1], cmd[-curs:]))
sys.stdout.write(
"\x08\x1B[K"
) # move cursor back, erase to end of line
sys.stdout.write(cmd[-curs:]) # redraw line
sys.stdout.write("\x1B[{}D".format(curs)) # reset cursor location
else:
cmd = cmd[:-1]
sys.stdout.write("\x08 \x08")
elif c == CHAR_CTRL_B: elif c == CHAR_CTRL_B:
continue continue
elif c == CHAR_CTRL_C: elif c == CHAR_CTRL_C:
@ -178,7 +191,7 @@ async def task(g=None, prompt="--> "):
elif c == 0x1B: elif c == 0x1B:
# Start of escape sequence. # Start of escape sequence.
key = await s.read(2) key = await s.read(2)
if key in ("[A", "[B"): if key in ("[A", "[B"): # up, down
# Stash the current command. # Stash the current command.
hist[(hist_i - hist_b) % _HISTORY_LIMIT] = cmd hist[(hist_i - hist_b) % _HISTORY_LIMIT] = cmd
# Clear current command. # Clear current command.
@ -194,12 +207,36 @@ async def task(g=None, prompt="--> "):
# 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) sys.stdout.write(cmd)
elif key == "[D": # left
if curs < len(cmd) - 1:
curs += 1
sys.stdout.write("\x1B")
sys.stdout.write(key)
elif key == "[C": # right
if curs:
curs -= 1
sys.stdout.write("\x1B")
sys.stdout.write(key)
elif key == "[H": # home
pcurs = curs
curs = len(cmd)
sys.stdout.write("\x1B[{}D".format(curs - pcurs)) # move cursor left
elif key == "[F": # end
pcurs = curs
curs = 0
sys.stdout.write("\x1B[{}C".format(pcurs)) # move cursor right
else: else:
# sys.stdout.write("\\x") # sys.stdout.write("\\x")
# sys.stdout.write(hex(c)) # sys.stdout.write(hex(c))
pass pass
else: else:
sys.stdout.write(b) if curs:
cmd += b # inserting into middle of line
cmd = "".join((cmd[:-curs], b, cmd[-curs:]))
sys.stdout.write(cmd[-curs - 1 :]) # redraw line to end
sys.stdout.write("\x1B[{}D".format(curs)) # reset cursor location
else:
sys.stdout.write(b)
cmd += b
finally: finally:
micropython.kbd_intr(3) micropython.kbd_intr(3)