Skip to content

Commit eae92aa

Browse files
committed
gh-118878: pyrepl: Show completion menu below current line
The main advantage of this is that the behaviour is less janky, since the current line no longer jumps up and down. This also allows fixing the behaviour of arrow keys when the menu is displayed.
1 parent dc98b55 commit eae92aa

File tree

3 files changed

+12
-7
lines changed

3 files changed

+12
-7
lines changed

Lib/_pyrepl/commands.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ def do(self) -> None:
276276
x, y = r.pos2xy()
277277
new_y = y + 1
278278

279-
if new_y > r.max_row():
279+
if r.eol() == len(b):
280280
if r.historyi < len(r.history):
281281
r.select_item(r.historyi + 1)
282282
r.pos = r.eol(0)
@@ -303,7 +303,7 @@ def do(self) -> None:
303303
class left(MotionCommand):
304304
def do(self) -> None:
305305
r = self.reader
306-
for i in range(r.get_arg()):
306+
for _ in range(r.get_arg()):
307307
p = r.pos - 1
308308
if p >= 0:
309309
r.pos = p
@@ -315,7 +315,7 @@ class right(MotionCommand):
315315
def do(self) -> None:
316316
r = self.reader
317317
b = r.buffer
318-
for i in range(r.get_arg()):
318+
for _ in range(r.get_arg()):
319319
p = r.pos + 1
320320
if p <= len(b):
321321
r.pos = p

Lib/_pyrepl/completing_reader.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
# types
3131
Command = commands.Command
3232
if False:
33-
from .types import Callback, SimpleContextManager, KeySpec, CommandName
33+
from .types import KeySpec, CommandName
3434

3535

3636
def prefix(wordlist: list[str], j: int = 0) -> str:
@@ -258,10 +258,14 @@ def after_command(self, cmd: Command) -> None:
258258
def calc_screen(self) -> list[str]:
259259
screen = super().calc_screen()
260260
if self.cmpltn_menu_vis:
261-
ly = self.lxy[1]
261+
ly = self.lxy[1] + 1
262262
screen[ly:ly] = self.cmpltn_menu
263-
self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
264-
self.cxy = self.cxy[0], self.cxy[1] + len(self.cmpltn_menu)
263+
# This is a horrible hack. If we're not in the middle
264+
# of multiline edit, don't append to screeninfo
265+
# since that screws up the position calculation
266+
# in pos2xy function.
267+
if self.pos != len(self.buffer):
268+
self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
265269
return screen
266270

267271
def finish(self) -> None:

Lib/test/test_pyrepl.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ def test_updown_arrow_with_completion_menu(self):
617617
events = itertools.chain(
618618
code_to_events(code),
619619
[
620+
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
620621
Event(evt='key', data='up', raw=bytearray(b'\x1bOA')),
621622
Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
622623
],

0 commit comments

Comments
 (0)