Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-132267: fix unsynchronized cursor position and buffer mismatch after resize#132313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
ImFeH2 wants to merge6 commits intopython:mainfromImFeH2:gh-132267
Closed
Show file tree
Hide file tree
Changes fromall 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
3 changes: 3 additions & 0 deletionsLib/_pyrepl/console.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -82,6 +82,9 @@ def restore(self) -> None: ...
@abstractmethod
def move_cursor(self, x: int, y: int) -> None: ...

@abstractmethod
def sync_screen(self) -> None: ...

@abstractmethod
def set_cursor_vis(self, visible: bool) -> None: ...

Expand Down
1 change: 1 addition & 0 deletionsLib/_pyrepl/reader.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -716,6 +716,7 @@ def handle1(self, block: bool = True) -> bool:
elif event.evt == "scroll":
self.refresh()
elif event.evt == "resize":
self.console.sync_screen()
self.refresh()
else:
translate = False
Expand Down
58 changes: 57 additions & 1 deletionLib/_pyrepl/unix_console.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -233,6 +233,7 @@ def refresh(self, screen, c_xy):
Parameters:
- screen (list): List of strings representing the screen contents.
- c_xy (tuple): Cursor position (x, y) on the screen.
- repaint (bool): If True, overwrite the old screen and not reuse.
"""
cx, cy = c_xy
if not self.__gone_tall:
Expand DownExpand Up@@ -324,6 +325,62 @@ def move_cursor(self, x, y):
self.posxy = x, y
self.flushoutput()

def sync_screen(self):
"""
Synchronize self.posxy, self.screen, self.width and self.height.
Assuming that the content of the screen doesn't change, only the width changes.
"""
if not self.screen:
self.posxy = 0, 0
return

px, py = self.posxy
old_height, old_width = self.height, self.width
new_height, new_width = self.getheightwidth()

groups = []
x, y = 0, 0
new_line = True
for i, line in enumerate(self.screen):
l = wlen(line)
if i == py:
if new_line:
y = sum(wlen(g) // new_width for g in groups) + len(groups) - 1
x = px
else:
y = sum(wlen(g) // new_width for g in groups[:-1]) + len(groups) - 1
x = px + wlen(groups[-1])
if x >= new_width:
y += x // new_width
x %= new_width

if new_line:
groups.append(line)
new_line = False
else:
groups[-1] += line
if l != old_width:
new_line = True

new_screen = []
for group in groups:
l = 0
line = ""
for c in group:
cw = wlen(c)
if l + cw > new_width:
new_screen.append(line)
line = c
l = cw
else:
line += c
l += cw
if line:
new_screen.append(line)

self.posxy = x, y
self.height, self.width = new_height, new_width

def prepare(self):
"""
Prepare the console for input/output operations.
Expand DownExpand Up@@ -757,7 +814,6 @@ def __move_tall(self, x, y):
self.__write_code(self._cup, y - self.__offset, x)

def __sigwinch(self, signum, frame):
self.height, self.width = self.getheightwidth()
self.event_queue.insert(Event("resize", None))

def __hide_cursor(self):
Expand Down
57 changes: 57 additions & 0 deletionsLib/_pyrepl/windows_console.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -165,6 +165,7 @@ def refresh(self, screen: list[str], c_xy: tuple[int, int]) -> None:
Parameters:
- screen (list): List of strings representing the screen contents.
- c_xy (tuple): Cursor position (x, y) on the screen.
- repaint (bool): If True, overwrite the old screen and not reuse.
"""
cx, cy = c_xy

Expand DownExpand Up@@ -384,6 +385,62 @@ def move_cursor(self, x: int, y: int) -> None:
self._move_relative(x, y)
self.posxy = x, y

def sync_screen(self):
"""
Synchronize self.posxy, self.screen, self.width and self.height.
Assuming that the content of the screen doesn't change, only the width changes.
"""
if not self.screen:
self.posxy = 0, 0
return

px, py = self.posxy
old_height, old_width = self.height, self.width
new_height, new_width = self.getheightwidth()

groups = []
x, y = 0, 0
new_line = True
for i, line in enumerate(self.screen):
l = wlen(line)
if i == py:
if new_line:
y = sum(wlen(g) // new_width for g in groups) + len(groups) - 1
x = px
else:
y = sum(wlen(g) // new_width for g in groups[:-1]) + len(groups) - 1
x = px + wlen(groups[-1])
if x >= new_width:
y += x // new_width
x %= new_width

if new_line:
groups.append(line)
new_line = False
else:
groups[-1] += line
if l != old_width:
new_line = True

new_screen = []
for group in groups:
l = 0
line = ""
for c in group:
cw = wlen(c)
if l + cw > new_width:
new_screen.append(line)
line = c
l = cw
else:
line += c
l += cw
if line:
new_screen.append(line)

self.posxy = x, y
self.height, self.width = new_height, new_width

def set_cursor_vis(self, visible: bool) -> None:
if visible:
self._show_cursor()
Expand Down
3 changes: 3 additions & 0 deletionsLib/test/test_pyrepl/support.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,6 +146,9 @@ def restore(self) -> None:
def move_cursor(self, x: int, y: int) -> None:
pass

def sync_screen(self) -> None:
pass

def set_cursor_vis(self, visible: bool) -> None:
pass

Expand Down
4 changes: 2 additions & 2 deletionsLib/test/test_pyrepl/test_unix_console.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@ def test_resize_bigger_on_multiline_function(self, _os_write):
)

console.height = 2
console.getheightwidth = MagicMock(lambda _:(2, 80))
console.getheightwidth = MagicMock(return_value=(2, 80))

def same_reader(_):
return reader
Expand DownExpand Up@@ -293,7 +293,7 @@ def test_resize_smaller_on_multiline_function(self, _os_write):
reader, console = handle_events_unix_console_height_3(events)

console.height = 1
console.getheightwidth = MagicMock(lambda _:(1, 80))
console.getheightwidth = MagicMock(return_value=(1, 80))

def same_reader(_):
return reader
Expand Down
8 changes: 4 additions & 4 deletionsLib/test/test_pyrepl/test_windows_console.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -89,7 +89,7 @@ def test_resize_wider(self):

console.height = 20
console.width = 80
console.getheightwidth = MagicMock(lambda _:(20, 80))
console.getheightwidth = MagicMock(return_value=(20, 80))

def same_reader(_):
return reader
Expand DownExpand Up@@ -117,7 +117,7 @@ def test_resize_narrower(self):

console.height = 20
console.width = 4
console.getheightwidth = MagicMock(lambda _:(20, 4))
console.getheightwidth = MagicMock(return_value=(20, 4))

def same_reader(_):
return reader
Expand DownExpand Up@@ -251,7 +251,7 @@ def test_resize_bigger_on_multiline_function(self):
reader, console = self.handle_events_short(events)

console.height = 2
console.getheightwidth = MagicMock(lambda _:(2, 80))
console.getheightwidth = MagicMock(return_value=(2, 80))

def same_reader(_):
return reader
Expand DownExpand Up@@ -289,7 +289,7 @@ def test_resize_smaller_on_multiline_function(self):
reader, console = self.handle_events_height_3(events)

console.height = 1
console.getheightwidth = MagicMock(lambda _:(1, 80))
console.getheightwidth = MagicMock(return_value=(1, 80))

def same_reader(_):
return reader
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Fix Console.posxy and Console.screen desynchronization caused by resize.
Loading

[8]ページ先頭

©2009-2025 Movatter.jp