Skip to content

Commit cfc3423

Browse files
committed
Fix Windows VT EOL wrap by syncing real console cursor
Windows VT terminals do not consistently wrap the cursor when a line exactly fills the terminal width. Previously we assumed a wrap always happened, which could desynchronize the logical cursor from the real console cursor and break subsequent cursor movement. This change queries the real cursor position and updates posxy accordingly, and adds regression tests for both wrap and no-wrap cases. Signed-off-by: Yongtao Huang <yongtaoh2022@gmail.com>
1 parent 6ea3f8c commit cfc3423

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

Lib/_pyrepl/windows_console.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,22 @@ def __write_changed_line(
272272

273273
self.__write(newline[x_pos:])
274274
if wlen(newline) == self.width:
275-
# If we wrapped we want to start at the next line
276-
self._move_relative(0, y + 1)
277-
self.posxy = 0, y + 1
275+
if self.__vt_support:
276+
info = CONSOLE_SCREEN_BUFFER_INFO()
277+
if not GetConsoleScreenBufferInfo(OutHandle, info):
278+
raise WinError(GetLastError())
279+
win_y = int(info.dwCursorPosition.Y - info.srWindow.Top)
280+
expected = y - self.__offset
281+
if win_y == expected + 1:
282+
# Terminal wrapped to next row.
283+
self.posxy = 0, y + 1
284+
else:
285+
# Terminal did not wrap; cursor stays at end-of-line.
286+
self.posxy = self.width, y
287+
else:
288+
# If we wrapped we want to start at the next line
289+
self._move_relative(0, y + 1)
290+
self.posxy = 0, y + 1
278291
else:
279292
self.posxy = wlen(newline), y
280293

0 commit comments

Comments
 (0)