mirror of
https://github.com/python/cpython.git
synced 2025-09-22 16:33:26 +00:00
gh-118878: Pyrepl: show completions menu below the current line (#118939)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
This commit is contained in:
parent
5a9afe2362
commit
29caec62ee
5 changed files with 17 additions and 9 deletions
|
@ -282,7 +282,7 @@ class down(MotionCommand):
|
||||||
x, y = r.pos2xy()
|
x, y = r.pos2xy()
|
||||||
new_y = y + 1
|
new_y = y + 1
|
||||||
|
|
||||||
if new_y > r.max_row():
|
if r.eol() == len(b):
|
||||||
if r.historyi < len(r.history):
|
if r.historyi < len(r.history):
|
||||||
r.select_item(r.historyi + 1)
|
r.select_item(r.historyi + 1)
|
||||||
r.pos = r.eol(0)
|
r.pos = r.eol(0)
|
||||||
|
@ -309,7 +309,7 @@ class down(MotionCommand):
|
||||||
class left(MotionCommand):
|
class left(MotionCommand):
|
||||||
def do(self) -> None:
|
def do(self) -> None:
|
||||||
r = self.reader
|
r = self.reader
|
||||||
for i in range(r.get_arg()):
|
for _ in range(r.get_arg()):
|
||||||
p = r.pos - 1
|
p = r.pos - 1
|
||||||
if p >= 0:
|
if p >= 0:
|
||||||
r.pos = p
|
r.pos = p
|
||||||
|
@ -321,7 +321,7 @@ class right(MotionCommand):
|
||||||
def do(self) -> None:
|
def do(self) -> None:
|
||||||
r = self.reader
|
r = self.reader
|
||||||
b = r.buffer
|
b = r.buffer
|
||||||
for i in range(r.get_arg()):
|
for _ in range(r.get_arg()):
|
||||||
p = r.pos + 1
|
p = r.pos + 1
|
||||||
if p <= len(b):
|
if p <= len(b):
|
||||||
r.pos = p
|
r.pos = p
|
||||||
|
|
|
@ -260,10 +260,15 @@ class CompletingReader(Reader):
|
||||||
def calc_screen(self) -> list[str]:
|
def calc_screen(self) -> list[str]:
|
||||||
screen = super().calc_screen()
|
screen = super().calc_screen()
|
||||||
if self.cmpltn_menu_visible:
|
if self.cmpltn_menu_visible:
|
||||||
ly = self.lxy[1]
|
# We display the completions menu below the current prompt
|
||||||
|
ly = self.lxy[1] + 1
|
||||||
screen[ly:ly] = self.cmpltn_menu
|
screen[ly:ly] = self.cmpltn_menu
|
||||||
|
# If we're not in the middle of multiline edit, don't append to screeninfo
|
||||||
|
# since that screws up the position calculation in pos2xy function.
|
||||||
|
# This is a hack to prevent the cursor jumping
|
||||||
|
# into the completions menu when pressing left or down arrow.
|
||||||
|
if self.pos != len(self.buffer):
|
||||||
self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
|
self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
|
||||||
self.cxy = self.cxy[0], self.cxy[1] + len(self.cmpltn_menu)
|
|
||||||
return screen
|
return screen
|
||||||
|
|
||||||
def finish(self) -> None:
|
def finish(self) -> None:
|
||||||
|
|
|
@ -850,7 +850,7 @@ class TestPyReplCompleter(TestCase):
|
||||||
output = multiline_input(reader, namespace)
|
output = multiline_input(reader, namespace)
|
||||||
self.assertEqual(output, "python")
|
self.assertEqual(output, "python")
|
||||||
|
|
||||||
def test_updown_arrow_with_completion_menu(self):
|
def test_up_down_arrow_with_completion_menu(self):
|
||||||
"""Up arrow in the middle of unfinished tab completion when the menu is displayed
|
"""Up arrow in the middle of unfinished tab completion when the menu is displayed
|
||||||
should work and trigger going back in history. Down arrow should subsequently
|
should work and trigger going back in history. Down arrow should subsequently
|
||||||
get us back to the incomplete command."""
|
get us back to the incomplete command."""
|
||||||
|
@ -860,6 +860,7 @@ class TestPyReplCompleter(TestCase):
|
||||||
events = itertools.chain(
|
events = itertools.chain(
|
||||||
code_to_events(code),
|
code_to_events(code),
|
||||||
[
|
[
|
||||||
|
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
|
||||||
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
|
Event(evt="key", data="up", raw=bytearray(b"\x1bOA")),
|
||||||
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
|
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
|
||||||
],
|
],
|
||||||
|
|
|
@ -295,8 +295,8 @@ class TestReader(TestCase):
|
||||||
|
|
||||||
actual = reader.screen
|
actual = reader.screen
|
||||||
self.assertEqual(len(actual), 2)
|
self.assertEqual(len(actual), 2)
|
||||||
self.assertEqual(actual[0].rstrip(), "itertools.accumulate(")
|
self.assertEqual(actual[0], f"{code}a")
|
||||||
self.assertEqual(actual[1], f"{code}a")
|
self.assertEqual(actual[1].rstrip(), "itertools.accumulate(")
|
||||||
|
|
||||||
def test_key_press_on_tab_press_once(self):
|
def test_key_press_on_tab_press_once(self):
|
||||||
namespace = {"itertools": itertools}
|
namespace = {"itertools": itertools}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Show tab completions menu below the current line, which results in less
|
||||||
|
janky behaviour, and fixes a cursor movement bug. Patch by Daniel Hollas
|
Loading…
Add table
Add a link
Reference in a new issue