mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-120041: Do not use append_to_screen when completions are visible (GH-120042)
This commit is contained in:
parent
4dcd91ceaf
commit
8fc7653766
4 changed files with 55 additions and 11 deletions
|
@ -365,7 +365,12 @@ class self_insert(EditCommand):
|
||||||
r = self.reader
|
r = self.reader
|
||||||
text = self.event * r.get_arg()
|
text = self.event * r.get_arg()
|
||||||
r.insert(text)
|
r.insert(text)
|
||||||
if len(text) == 1 and r.pos == len(r.buffer):
|
if (
|
||||||
|
len(text) == 1 and
|
||||||
|
r.pos == len(r.buffer) and
|
||||||
|
not r.cmpltn_menu_visible and # type: ignore[attr-defined]
|
||||||
|
not r.cmpltn_message_visible # type: ignore[attr-defined]
|
||||||
|
):
|
||||||
r.calc_screen = r.append_to_screen
|
r.calc_screen = r.append_to_screen
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -187,13 +187,15 @@ class complete(commands.Command):
|
||||||
if p:
|
if p:
|
||||||
r.insert(p)
|
r.insert(p)
|
||||||
if last_is_completer:
|
if last_is_completer:
|
||||||
if not r.cmpltn_menu_visible:
|
|
||||||
r.cmpltn_menu_visible = True
|
r.cmpltn_menu_visible = True
|
||||||
|
r.cmpltn_message_visible = False
|
||||||
r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
|
r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
|
||||||
r.console, completions, r.cmpltn_menu_end,
|
r.console, completions, r.cmpltn_menu_end,
|
||||||
r.use_brackets, r.sort_in_column)
|
r.use_brackets, r.sort_in_column)
|
||||||
r.dirty = True
|
r.dirty = True
|
||||||
elif stem + p in completions:
|
elif not r.cmpltn_menu_visible:
|
||||||
|
r.cmpltn_message_visible = True
|
||||||
|
if stem + p in completions:
|
||||||
r.msg = "[ complete but not unique ]"
|
r.msg = "[ complete but not unique ]"
|
||||||
r.dirty = True
|
r.dirty = True
|
||||||
else:
|
else:
|
||||||
|
@ -236,6 +238,7 @@ class CompletingReader(Reader):
|
||||||
### Instance variables
|
### Instance variables
|
||||||
cmpltn_menu: list[str] = field(init=False)
|
cmpltn_menu: list[str] = field(init=False)
|
||||||
cmpltn_menu_visible: bool = field(init=False)
|
cmpltn_menu_visible: bool = field(init=False)
|
||||||
|
cmpltn_message_visible: bool = field(init=False)
|
||||||
cmpltn_menu_end: int = field(init=False)
|
cmpltn_menu_end: int = field(init=False)
|
||||||
cmpltn_menu_choices: list[str] = field(init=False)
|
cmpltn_menu_choices: list[str] = field(init=False)
|
||||||
|
|
||||||
|
@ -271,6 +274,7 @@ class CompletingReader(Reader):
|
||||||
def cmpltn_reset(self) -> None:
|
def cmpltn_reset(self) -> None:
|
||||||
self.cmpltn_menu = []
|
self.cmpltn_menu = []
|
||||||
self.cmpltn_menu_visible = False
|
self.cmpltn_menu_visible = False
|
||||||
|
self.cmpltn_message_visible = False
|
||||||
self.cmpltn_menu_end = 0
|
self.cmpltn_menu_end = 0
|
||||||
self.cmpltn_menu_choices = []
|
self.cmpltn_menu_choices = []
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ def code_to_events(code: str):
|
||||||
|
|
||||||
|
|
||||||
def prepare_reader(console: Console, **kwargs):
|
def prepare_reader(console: Console, **kwargs):
|
||||||
config = ReadlineConfig(readline_completer=None)
|
config = ReadlineConfig(readline_completer=kwargs.pop("readline_completer", None))
|
||||||
reader = ReadlineAlikeReader(console=console, config=config)
|
reader = ReadlineAlikeReader(console=console, config=config)
|
||||||
reader.more_lines = partial(more_lines, namespace=None)
|
reader.more_lines = partial(more_lines, namespace=None)
|
||||||
reader.paste_mode = True # Avoid extra indents
|
reader.paste_mode = True # Avoid extra indents
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import itertools
|
import itertools
|
||||||
import functools
|
import functools
|
||||||
|
import rlcompleter
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from .support import handle_all_events, handle_events_narrow_console, code_to_events, prepare_reader
|
from .support import handle_all_events, handle_events_narrow_console, code_to_events, prepare_reader
|
||||||
|
@ -9,7 +10,7 @@ from _pyrepl.reader import Reader
|
||||||
|
|
||||||
class TestReader(TestCase):
|
class TestReader(TestCase):
|
||||||
def assert_screen_equals(self, reader, expected):
|
def assert_screen_equals(self, reader, expected):
|
||||||
actual = reader.calc_screen()
|
actual = reader.screen
|
||||||
expected = expected.split("\n")
|
expected = expected.split("\n")
|
||||||
self.assertListEqual(actual, expected)
|
self.assertListEqual(actual, expected)
|
||||||
|
|
||||||
|
@ -208,3 +209,37 @@ class TestReader(TestCase):
|
||||||
prompt, l = Reader.process_prompt(ps1)
|
prompt, l = Reader.process_prompt(ps1)
|
||||||
self.assertEqual(prompt, "\033[0;32m樂>\033[0m> ")
|
self.assertEqual(prompt, "\033[0;32m樂>\033[0m> ")
|
||||||
self.assertEqual(l, 5)
|
self.assertEqual(l, 5)
|
||||||
|
|
||||||
|
def test_completions_updated_on_key_press(self):
|
||||||
|
namespace = {"itertools": itertools}
|
||||||
|
code = "itertools."
|
||||||
|
events = itertools.chain(code_to_events(code), [
|
||||||
|
Event(evt='key', data='\t', raw=bytearray(b'\t')), # Two tabs for completion
|
||||||
|
Event(evt='key', data='\t', raw=bytearray(b'\t')),
|
||||||
|
], code_to_events("a"))
|
||||||
|
|
||||||
|
completing_reader = functools.partial(
|
||||||
|
prepare_reader,
|
||||||
|
readline_completer=rlcompleter.Completer(namespace).complete
|
||||||
|
)
|
||||||
|
reader, _ = handle_all_events(events, prepare_reader=completing_reader)
|
||||||
|
|
||||||
|
actual = reader.screen
|
||||||
|
self.assertEqual(len(actual), 2)
|
||||||
|
self.assertEqual(actual[0].rstrip(), "itertools.accumulate(")
|
||||||
|
self.assertEqual(actual[1], f"{code}a")
|
||||||
|
|
||||||
|
def test_key_press_on_tab_press_once(self):
|
||||||
|
namespace = {"itertools": itertools}
|
||||||
|
code = "itertools."
|
||||||
|
events = itertools.chain(code_to_events(code), [
|
||||||
|
Event(evt='key', data='\t', raw=bytearray(b'\t')),
|
||||||
|
], code_to_events("a"))
|
||||||
|
|
||||||
|
completing_reader = functools.partial(
|
||||||
|
prepare_reader,
|
||||||
|
readline_completer=rlcompleter.Completer(namespace).complete
|
||||||
|
)
|
||||||
|
reader, _ = handle_all_events(events, prepare_reader=completing_reader)
|
||||||
|
|
||||||
|
self.assert_screen_equals(reader, f"{code}a")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue