aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-06-04 20:10:29 +0200
committerGitHub <noreply@github.com>2024-06-04 18:10:29 +0000
commit8d74eae4d492f23f33757b05f7de2cdbe210760e (patch)
treeb3604489b7eab400f134aa18eba3a46b4c3c62b4
parent[3.13] gh-89928: Fix integer conversion of device numbers (GH-31794) (GH-120053) (diff)
downloadcpython-8d74eae4d492f23f33757b05f7de2cdbe210760e.tar.gz
cpython-8d74eae4d492f23f33757b05f7de2cdbe210760e.tar.bz2
cpython-8d74eae4d492f23f33757b05f7de2cdbe210760e.zip
[3.13] gh-120041: Do not use append_to_screen when completions are visible (GH-120042) (#120051)
* gh-120041: Do not use append_to_screen when completions are visible (GH-120042) (cherry picked from commit 8fc7653766b106bdbc4ff6154e0020aea4ab15e6) * gh-120041: Refactor check for visible completion menu in completing_reader (GH-120055) (cherry picked from commit bf8e5e53d0c359a1f9c285d855e7a5e9b6d91375) --------- Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
-rw-r--r--Lib/_pyrepl/completing_reader.py23
-rw-r--r--Lib/test/test_pyrepl/support.py2
-rw-r--r--Lib/test/test_pyrepl/test_reader.py37
3 files changed, 52 insertions, 10 deletions
diff --git a/Lib/_pyrepl/completing_reader.py b/Lib/_pyrepl/completing_reader.py
index c11d2dabdd2..8df35ccb911 100644
--- a/Lib/_pyrepl/completing_reader.py
+++ b/Lib/_pyrepl/completing_reader.py
@@ -187,18 +187,20 @@ class complete(commands.Command):
if p:
r.insert(p)
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.console, completions, r.cmpltn_menu_end,
r.use_brackets, r.sort_in_column)
r.dirty = True
- elif stem + p in completions:
- r.msg = "[ complete but not unique ]"
- r.dirty = True
- else:
- r.msg = "[ not unique ]"
- r.dirty = True
+ elif not r.cmpltn_menu_visible:
+ r.cmpltn_message_visible = True
+ if stem + p in completions:
+ r.msg = "[ complete but not unique ]"
+ r.dirty = True
+ else:
+ r.msg = "[ not unique ]"
+ r.dirty = True
class self_insert(commands.self_insert):
@@ -208,6 +210,9 @@ class self_insert(commands.self_insert):
commands.self_insert.do(self)
+ if r.cmpltn_menu_visible or r.cmpltn_message_visible:
+ r.calc_screen = r.calc_complete_screen
+
if r.cmpltn_menu_visible:
stem = r.get_stem()
if len(stem) < 1:
@@ -236,6 +241,7 @@ class CompletingReader(Reader):
### Instance variables
cmpltn_menu: list[str] = 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_choices: list[str] = field(init=False)
@@ -271,6 +277,7 @@ class CompletingReader(Reader):
def cmpltn_reset(self) -> None:
self.cmpltn_menu = []
self.cmpltn_menu_visible = False
+ self.cmpltn_message_visible = False
self.cmpltn_menu_end = 0
self.cmpltn_menu_choices = []
diff --git a/Lib/test/test_pyrepl/support.py b/Lib/test/test_pyrepl/support.py
index d2f5429aea7..e807b5f3404 100644
--- a/Lib/test/test_pyrepl/support.py
+++ b/Lib/test/test_pyrepl/support.py
@@ -39,7 +39,7 @@ def code_to_events(code: str):
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.more_lines = partial(more_lines, namespace=None)
reader.paste_mode = True # Avoid extra indents
diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py
index 9fb956b6555..d02815bfa11 100644
--- a/Lib/test/test_pyrepl/test_reader.py
+++ b/Lib/test/test_pyrepl/test_reader.py
@@ -1,5 +1,6 @@
import itertools
import functools
+import rlcompleter
from unittest import TestCase
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):
def assert_screen_equals(self, reader, expected):
- actual = reader.calc_screen()
+ actual = reader.screen
expected = expected.split("\n")
self.assertListEqual(actual, expected)
@@ -208,3 +209,37 @@ class TestReader(TestCase):
prompt, l = Reader.process_prompt(ps1)
self.assertEqual(prompt, "\033[0;32m樂>\033[0m> ")
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")