Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions Lib/_pyrepl/windows_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,18 +270,13 @@ def __write_changed_line(
self._erase_to_end()

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

if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
# ANSI escape characters are present, so we can't assume
# anything about the position of the cursor. Moving the cursor
# to the left margin should work to get to a known position.
self.move_cursor(0, y)
if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
# ANSI escape characters are present, so we can't assume
# anything about the position of the cursor. Moving the cursor
# to the left margin should work to get to a known position.
self.move_cursor(0, y)

def _scroll(
self, top: int, bottom: int, left: int | None = None, right: int | None = None
Expand Down
46 changes: 45 additions & 1 deletion Lib/test/test_pyrepl/test_pyrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import tempfile
from pkgutil import ModuleInfo
from unittest import TestCase, skipUnless, skipIf, SkipTest
from unittest.mock import patch
from unittest.mock import Mock, patch
from test.support import force_not_colorized, make_clean_env, Py_DEBUG
from test.support import has_subprocess_support, SHORT_TIMEOUT, STDLIB_DIR
from test.support.import_helper import import_module
Expand Down Expand Up @@ -2105,3 +2105,47 @@ def test_ctrl_d_single_line_end_no_newline(self):
)
reader, _ = handle_all_events(events)
self.assertEqual("hello", "".join(reader.buffer))


@skipUnless(sys.platform == "win32", "windows console only")
class TestWindowsConsoleEolWrap(TestCase):
def _make_mock_console(self, width=80):
from _pyrepl import windows_console as wc

console = object.__new__(wc.WindowsConsole)

console.width = width
console.posxy = (0, 0)
console.screen = [""]

console._hide_cursor = Mock()
console._show_cursor = Mock()
console._erase_to_end = Mock()
console._move_relative = Mock()
console.move_cursor = Mock()
console._WindowsConsole__write = Mock()

return console, wc

def test_short_line_sets_posxy_normally(self):
width = 10
y = 3
console, wc = self._make_mock_console(width=width)
old_line = ""
new_line = "a" * 3
wc.WindowsConsole._WindowsConsole__write_changed_line(
console, y, old_line, new_line, 0
)
self.assertEqual(console.posxy, (3, y))

def test_exact_width_line_does_not_wrap(self):
width = 10
y = 3
console, wc = self._make_mock_console(width=width)
old_line = ""
new_line = "a" * width

wc.WindowsConsole._WindowsConsole__write_changed_line(
console, y, old_line, new_line, 0
)
self.assertEqual(console.posxy, (width - 1, y))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix inconsistent display of long multiline pasted content in the REPL.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix REPL cursor position on Windows when module completion suggestion line
hits console width.
Loading