Skip to content

Commit 80121e1

Browse files
committed
fix: refresh line-by-line instead of clearing entire screen
1 parent 1b7c1b8 commit 80121e1

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

Lib/_pyrepl/console.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def __init__(
7171
self.output_fd = f_out.fileno()
7272

7373
@abstractmethod
74-
def refresh(self, screen: list[str], xy: tuple[int, int]) -> None: ...
74+
def refresh(self, screen: list[str], xy: tuple[int, int], clear_to_end: bool = False) -> None: ...
7575

7676
@abstractmethod
7777
def prepare(self) -> None: ...
@@ -82,6 +82,9 @@ def restore(self) -> None: ...
8282
@abstractmethod
8383
def move_cursor(self, x: int, y: int) -> None: ...
8484

85+
@abstractmethod
86+
def reset_cursor(self) -> None: ...
87+
8588
@abstractmethod
8689
def set_cursor_vis(self, visible: bool) -> None: ...
8790

Lib/_pyrepl/reader.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,17 @@ def refresh(self) -> None:
641641
self.console.refresh(self.screen, self.cxy)
642642
self.dirty = False
643643

644+
def handle_resize(self) -> None:
645+
"""Handle a resize event."""
646+
self.console.height, self.console.width = self.console.getheightwidth()
647+
self.console.reset_cursor()
648+
ns = len(self.console.screen) * ["\000" * self.console.width]
649+
self.console.screen = ns
650+
651+
self.screen = self.calc_screen()
652+
self.console.refresh(self.screen, self.cxy, clear_to_end=True)
653+
self.dirty = True
654+
644655
def do_cmd(self, cmd: tuple[str, list[str]]) -> None:
645656
"""`cmd` is a tuple of "event_name" and "event", which in the current
646657
implementation is always just the "buffer" which happens to be a list
@@ -716,9 +727,7 @@ def handle1(self, block: bool = True) -> bool:
716727
elif event.evt == "scroll":
717728
self.refresh()
718729
elif event.evt == "resize":
719-
self.console.height, self.console.width = self.console.getheightwidth()
720-
self.console.clear()
721-
self.refresh()
730+
self.handle_resize()
722731
else:
723732
translate = False
724733

Lib/_pyrepl/unix_console.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def change_encoding(self, encoding: str) -> None:
223223
"""
224224
self.encoding = encoding
225225

226-
def refresh(self, screen, c_xy):
226+
def refresh(self, screen, c_xy, clear_to_end = False):
227227
"""
228228
Refresh the console screen.
229229
@@ -301,6 +301,12 @@ def refresh(self, screen, c_xy):
301301
self.__write_code(self._el)
302302
y += 1
303303

304+
if clear_to_end:
305+
self.__move(wlen(newscr[-1]), len(newscr) - 1 + self.__offset)
306+
self.posxy = wlen(newscr[-1]), len(newscr) - 1 + self.__offset
307+
self.__write_code(b"\x1b[J") # clear to end of line
308+
self.flushoutput()
309+
304310
self.__show_cursor()
305311

306312
self.screen = screen.copy()
@@ -322,6 +328,10 @@ def move_cursor(self, x, y):
322328
self.posxy = x, y
323329
self.flushoutput()
324330

331+
def reset_cursor(self) -> None:
332+
self.posxy = 0, self.__offset
333+
self.__write_code(self._cup, 0, 0)
334+
325335
def prepare(self):
326336
"""
327337
Prepare the console for input/output operations.

Lib/_pyrepl/windows_console.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def __init__(self, err: int | None, descr: str | None = None) -> None:
111111
MOVE_UP = "\x1b[{}A"
112112
MOVE_DOWN = "\x1b[{}B"
113113
CLEAR = "\x1b[H\x1b[J"
114+
HOME = "\x1b[H"
114115

115116
# State of control keys: https://learn.microsoft.com/en-us/windows/console/key-event-record-str
116117
ALT_ACTIVE = 0x01 | 0x02
@@ -171,7 +172,7 @@ def __init__(
171172
# Console I/O is redirected, fallback...
172173
self.out = None
173174

174-
def refresh(self, screen: list[str], c_xy: tuple[int, int]) -> None:
175+
def refresh(self, screen: list[str], c_xy: tuple[int, int], clear_to_end: bool = False) -> None:
175176
"""
176177
Refresh the console screen.
177178
@@ -237,6 +238,12 @@ def refresh(self, screen: list[str], c_xy: tuple[int, int]) -> None:
237238
self._erase_to_end()
238239
y += 1
239240

241+
if clear_to_end:
242+
self._move_relative(wlen(newscr[-1]), self.__offset + len(newscr) - 1)
243+
self.posxy = wlen(newscr[-1]), self.__offset + len(newscr) - 1
244+
self.__write("\x1b[J")
245+
self.flushoutput()
246+
240247
self._show_cursor()
241248

242249
self.screen = screen
@@ -398,6 +405,10 @@ def move_cursor(self, x: int, y: int) -> None:
398405
self._move_relative(x, y)
399406
self.posxy = x, y
400407

408+
def reset_cursor(self) -> None:
409+
self.posxy = 0, self.__offset
410+
self.__write(HOME)
411+
401412
def set_cursor_vis(self, visible: bool) -> None:
402413
if visible:
403414
self._show_cursor()

0 commit comments

Comments
 (0)