Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

aiorepl: Add tab completion support. #1081

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
andrewleech wants to merge 1 commit into micropython:master
base: master
Choose a base branch
Loading
from andrewleech:aiorepl-tab-completion
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion micropython/aiorepl/README.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Ctrl-D at the asyncio REPL command prompt will terminate the current event loop,

The following features are unsupported:

* Tab completion is not supported (also unsupported in `python -m asyncio`).
* Tab completion requires `micropython.repl_autocomplete` (available when firmware is built with `MICROPY_HELPER_REPL`, which is the default for most ports).
* Multi-line continuation. However you can do single-line definitions of functions, see demo above.
* Exception tracebacks. Only the exception type and message is shown, see demo above.
* Emacs shortcuts (e.g. Ctrl-A, Ctrl-E, to move to start/end of line).
Expand Down
26 changes: 26 additions & 0 deletions micropython/aiorepl/aiorepl.py
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ async def task(g=None, prompt="--> "):
hist_n = 0 # Number of history entries.
c = 0 # ord of most recent character.
t = 0 # timestamp of most recent character.
_autocomplete = getattr(micropython, "repl_autocomplete", None)
while True:
hist_b = 0 # How far back in the history are we currently.
sys.stdout.write(prompt)
Expand Down Expand Up @@ -187,6 +188,31 @@ async def task(g=None, prompt="--> "):
elif c == CHAR_CTRL_E:
sys.stdout.write("paste mode; Ctrl-C to cancel, Ctrl-D to finish\n===\n")
paste = True
elif c == 0x09 and not paste:
# Tab key.
cursor_pos = len(cmd) - curs
if cursor_pos > 0 and cmd[cursor_pos - 1] <= " ":
# Insert 4 spaces for indentation after whitespace.
compl = " "
elif _autocomplete and cursor_pos > 0:
compl = _autocomplete(cmd[:cursor_pos])
else:
compl = ""
if compl:
# Insert completion at cursor.
if curs:
cmd = "".join((cmd[:-curs], compl, cmd[-curs:]))
sys.stdout.write(cmd[-curs - len(compl) :])
sys.stdout.write("\x1b[{}D".format(curs))
else:
sys.stdout.write(compl)
cmd += compl
elif compl is None:
# Multiple matches printed by autocomplete, redraw line.
sys.stdout.write(prompt)
sys.stdout.write(cmd)
if curs:
sys.stdout.write("\x1b[{}D".format(curs))
elif c == 0x1B:
# Start of escape sequence.
key = await s.read(2)
Expand Down
2 changes: 1 addition & 1 deletion micropython/aiorepl/manifest.py
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
metadata(
version="0.2.2",
version="0.3.0",
description="Provides an asynchronous REPL that can run concurrently with an asyncio, also allowing await expressions.",
)

Expand Down
43 changes: 43 additions & 0 deletions micropython/aiorepl/test_autocomplete.py
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Test tab completion logic used by aiorepl.
import sys
import micropython

try:
micropython.repl_autocomplete
except AttributeError:
print("SKIP")
raise SystemExit

# Test the autocomplete API contract that aiorepl depends on.

# Single completion: keyword "import"
result = micropython.repl_autocomplete("impo")
print(repr(result))

# No match: returns empty string
result = micropython.repl_autocomplete("xyz_no_match_zzz")
print(repr(result))

# Multiple matches: returns None (candidates printed to stdout by C code).
# Create two globals sharing a prefix so autocomplete finds multiple matches.
import __main__

Check failure on line 23 in micropython/aiorepl/test_autocomplete.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E402)

micropython/aiorepl/test_autocomplete.py:23:1: E402 Module level import not at top of file

__main__.tvar_alpha = 1
__main__.tvar_beta = 2
result = micropython.repl_autocomplete("tvar_")
del __main__.tvar_alpha
del __main__.tvar_beta
print("multiple:", repr(result))

# Test the whitespace-before-cursor logic used for tab-as-indentation.
# This validates the condition: cursor_pos > 0 and cmd[cursor_pos - 1] <= " "
test_cases = [
("x ", True), # space before cursor
("x", False), # non-whitespace before cursor
("\n", True), # newline counts as whitespace
("", False), # empty line (cursor_pos == 0)
]
for cmd, expected in test_cases:
cursor_pos = len(cmd)
is_whitespace = cursor_pos > 0 and cmd[cursor_pos - 1] <= " "
print(cmd.encode(), is_whitespace == expected)
9 changes: 9 additions & 0 deletions micropython/aiorepl/test_autocomplete.py.exp
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'rt '
''

tvar_alpha tvar_beta
multiple: None
b'x ' True
b'x' True
b'\n' True
b'' True
Loading

AltStyle によって変換されたページ (->オリジナル) /