Skip to content

Commit 6669b20

Browse files
[3.14] gh-140131: Fix REPL cursor position on Windows when module completion suggestion line hits console width (GH-140333) (GH-145871)
(cherry picked from commit e13f6dc) Co-authored-by: Tan Long <tanloong@foxmail.com>
1 parent f9589cb commit 6669b20

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

Lib/_pyrepl/windows_console.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -283,18 +283,13 @@ def __write_changed_line(
283283
self._erase_to_end()
284284

285285
self.__write(newline[x_pos:])
286-
if wlen(newline) == self.width:
287-
# If we wrapped we want to start at the next line
288-
self._move_relative(0, y + 1)
289-
self.posxy = 0, y + 1
290-
else:
291-
self.posxy = wlen(newline), y
286+
self.posxy = min(wlen(newline), self.width - 1), y
292287

293-
if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
294-
# ANSI escape characters are present, so we can't assume
295-
# anything about the position of the cursor. Moving the cursor
296-
# to the left margin should work to get to a known position.
297-
self.move_cursor(0, y)
288+
if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
289+
# ANSI escape characters are present, so we can't assume
290+
# anything about the position of the cursor. Moving the cursor
291+
# to the left margin should work to get to a known position.
292+
self.move_cursor(0, y)
298293

299294
def _scroll(
300295
self, top: int, bottom: int, left: int | None = None, right: int | None = None

Lib/test/test_pyrepl/test_pyrepl.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import tempfile
1313
from pkgutil import ModuleInfo
1414
from unittest import TestCase, skipUnless, skipIf, SkipTest
15-
from unittest.mock import patch
15+
from unittest.mock import Mock, patch
1616
from test.support import force_not_colorized, make_clean_env, Py_DEBUG
1717
from test.support import has_subprocess_support, SHORT_TIMEOUT, STDLIB_DIR
1818
from test.support.import_helper import import_module
@@ -2095,3 +2095,47 @@ def test_ctrl_d_single_line_end_no_newline(self):
20952095
)
20962096
reader, _ = handle_all_events(events)
20972097
self.assertEqual("hello", "".join(reader.buffer))
2098+
2099+
2100+
@skipUnless(sys.platform == "win32", "windows console only")
2101+
class TestWindowsConsoleEolWrap(TestCase):
2102+
def _make_mock_console(self, width=80):
2103+
from _pyrepl import windows_console as wc
2104+
2105+
console = object.__new__(wc.WindowsConsole)
2106+
2107+
console.width = width
2108+
console.posxy = (0, 0)
2109+
console.screen = [""]
2110+
2111+
console._hide_cursor = Mock()
2112+
console._show_cursor = Mock()
2113+
console._erase_to_end = Mock()
2114+
console._move_relative = Mock()
2115+
console.move_cursor = Mock()
2116+
console._WindowsConsole__write = Mock()
2117+
2118+
return console, wc
2119+
2120+
def test_short_line_sets_posxy_normally(self):
2121+
width = 10
2122+
y = 3
2123+
console, wc = self._make_mock_console(width=width)
2124+
old_line = ""
2125+
new_line = "a" * 3
2126+
wc.WindowsConsole._WindowsConsole__write_changed_line(
2127+
console, y, old_line, new_line, 0
2128+
)
2129+
self.assertEqual(console.posxy, (3, y))
2130+
2131+
def test_exact_width_line_does_not_wrap(self):
2132+
width = 10
2133+
y = 3
2134+
console, wc = self._make_mock_console(width=width)
2135+
old_line = ""
2136+
new_line = "a" * width
2137+
2138+
wc.WindowsConsole._WindowsConsole__write_changed_line(
2139+
console, y, old_line, new_line, 0
2140+
)
2141+
self.assertEqual(console.posxy, (width - 1, y))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix inconsistent display of long multiline pasted content in the REPL.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix REPL cursor position on Windows when module completion suggestion line
2+
hits console width.

0 commit comments

Comments
 (0)