mirror of
https://github.com/python/cpython.git
synced 2025-09-15 13:16:12 +00:00
[3.13] gh-111201: Add append to screen method to avoid recalculation (GH-119274) (#119405)
(cherry picked from commit c886bece3b
)
Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
parent
ac9163637b
commit
aefe2e626e
4 changed files with 43 additions and 14 deletions
|
@ -358,7 +358,10 @@ class backward_word(MotionCommand):
|
||||||
class self_insert(EditCommand):
|
class self_insert(EditCommand):
|
||||||
def do(self) -> None:
|
def do(self) -> None:
|
||||||
r = self.reader
|
r = self.reader
|
||||||
r.insert(self.event * r.get_arg())
|
text = self.event * r.get_arg()
|
||||||
|
r.insert(text)
|
||||||
|
if len(text) == 1 and r.pos == len(r.buffer):
|
||||||
|
r.calc_screen = r.append_to_screen
|
||||||
|
|
||||||
|
|
||||||
class insert_nl(EditCommand):
|
class insert_nl(EditCommand):
|
||||||
|
|
|
@ -187,8 +187,8 @@ class complete(commands.Command):
|
||||||
if p:
|
if p:
|
||||||
r.insert(p)
|
r.insert(p)
|
||||||
if last_is_completer:
|
if last_is_completer:
|
||||||
if not r.cmpltn_menu_vis:
|
if not r.cmpltn_menu_visible:
|
||||||
r.cmpltn_menu_vis = 1
|
r.cmpltn_menu_visible = True
|
||||||
r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
|
r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
|
||||||
r.console, completions, r.cmpltn_menu_end,
|
r.console, completions, r.cmpltn_menu_end,
|
||||||
r.use_brackets, r.sort_in_column)
|
r.use_brackets, r.sort_in_column)
|
||||||
|
@ -208,7 +208,7 @@ class self_insert(commands.self_insert):
|
||||||
|
|
||||||
commands.self_insert.do(self)
|
commands.self_insert.do(self)
|
||||||
|
|
||||||
if r.cmpltn_menu_vis:
|
if r.cmpltn_menu_visible:
|
||||||
stem = r.get_stem()
|
stem = r.get_stem()
|
||||||
if len(stem) < 1:
|
if len(stem) < 1:
|
||||||
r.cmpltn_reset()
|
r.cmpltn_reset()
|
||||||
|
@ -235,7 +235,7 @@ class CompletingReader(Reader):
|
||||||
|
|
||||||
### Instance variables
|
### Instance variables
|
||||||
cmpltn_menu: list[str] = field(init=False)
|
cmpltn_menu: list[str] = field(init=False)
|
||||||
cmpltn_menu_vis: int = field(init=False)
|
cmpltn_menu_visible: bool = field(init=False)
|
||||||
cmpltn_menu_end: int = field(init=False)
|
cmpltn_menu_end: int = field(init=False)
|
||||||
cmpltn_menu_choices: list[str] = field(init=False)
|
cmpltn_menu_choices: list[str] = field(init=False)
|
||||||
|
|
||||||
|
@ -255,9 +255,9 @@ class CompletingReader(Reader):
|
||||||
if not isinstance(cmd, (complete, self_insert)):
|
if not isinstance(cmd, (complete, self_insert)):
|
||||||
self.cmpltn_reset()
|
self.cmpltn_reset()
|
||||||
|
|
||||||
def calc_screen(self) -> list[str]:
|
def calc_complete_screen(self) -> list[str]:
|
||||||
screen = super().calc_screen()
|
screen = super().calc_complete_screen()
|
||||||
if self.cmpltn_menu_vis:
|
if self.cmpltn_menu_visible:
|
||||||
ly = self.lxy[1]
|
ly = self.lxy[1]
|
||||||
screen[ly:ly] = self.cmpltn_menu
|
screen[ly:ly] = self.cmpltn_menu
|
||||||
self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
|
self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
|
||||||
|
@ -270,7 +270,7 @@ class CompletingReader(Reader):
|
||||||
|
|
||||||
def cmpltn_reset(self) -> None:
|
def cmpltn_reset(self) -> None:
|
||||||
self.cmpltn_menu = []
|
self.cmpltn_menu = []
|
||||||
self.cmpltn_menu_vis = 0
|
self.cmpltn_menu_visible = False
|
||||||
self.cmpltn_menu_end = 0
|
self.cmpltn_menu_end = 0
|
||||||
self.cmpltn_menu_choices = []
|
self.cmpltn_menu_choices = []
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,9 @@ from .trace import trace
|
||||||
# types
|
# types
|
||||||
Command = commands.Command
|
Command = commands.Command
|
||||||
if False:
|
if False:
|
||||||
|
from typing import Callable
|
||||||
from .types import Callback, SimpleContextManager, KeySpec, CommandName
|
from .types import Callback, SimpleContextManager, KeySpec, CommandName
|
||||||
|
CalcScreen = Callable[[], list[str]]
|
||||||
|
|
||||||
|
|
||||||
def disp_str(buffer: str) -> tuple[str, list[int]]:
|
def disp_str(buffer: str) -> tuple[str, list[int]]:
|
||||||
|
@ -231,9 +233,11 @@ class Reader:
|
||||||
keymap: tuple[tuple[str, str], ...] = ()
|
keymap: tuple[tuple[str, str], ...] = ()
|
||||||
input_trans: input.KeymapTranslator = field(init=False)
|
input_trans: input.KeymapTranslator = field(init=False)
|
||||||
input_trans_stack: list[input.KeymapTranslator] = field(default_factory=list)
|
input_trans_stack: list[input.KeymapTranslator] = field(default_factory=list)
|
||||||
|
screen: list[str] = field(default_factory=list)
|
||||||
screeninfo: list[tuple[int, list[int]]] = field(init=False)
|
screeninfo: list[tuple[int, list[int]]] = field(init=False)
|
||||||
cxy: tuple[int, int] = field(init=False)
|
cxy: tuple[int, int] = field(init=False)
|
||||||
lxy: tuple[int, int] = field(init=False)
|
lxy: tuple[int, int] = field(init=False)
|
||||||
|
calc_screen: CalcScreen = field(init=False)
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
# Enable the use of `insert` without a `prepare` call - necessary to
|
# Enable the use of `insert` without a `prepare` call - necessary to
|
||||||
|
@ -243,14 +247,36 @@ class Reader:
|
||||||
self.input_trans = input.KeymapTranslator(
|
self.input_trans = input.KeymapTranslator(
|
||||||
self.keymap, invalid_cls="invalid-key", character_cls="self-insert"
|
self.keymap, invalid_cls="invalid-key", character_cls="self-insert"
|
||||||
)
|
)
|
||||||
self.screeninfo = [(0, [0])]
|
self.screeninfo = [(0, [])]
|
||||||
self.cxy = self.pos2xy()
|
self.cxy = self.pos2xy()
|
||||||
self.lxy = (self.pos, 0)
|
self.lxy = (self.pos, 0)
|
||||||
|
self.calc_screen = self.calc_complete_screen
|
||||||
|
|
||||||
def collect_keymap(self) -> tuple[tuple[KeySpec, CommandName], ...]:
|
def collect_keymap(self) -> tuple[tuple[KeySpec, CommandName], ...]:
|
||||||
return default_keymap
|
return default_keymap
|
||||||
|
|
||||||
def calc_screen(self) -> list[str]:
|
def append_to_screen(self) -> list[str]:
|
||||||
|
new_screen = self.screen.copy() or ['']
|
||||||
|
|
||||||
|
new_character = self.buffer[-1]
|
||||||
|
new_character_len = wlen(new_character)
|
||||||
|
|
||||||
|
last_line_len = wlen(new_screen[-1])
|
||||||
|
if last_line_len + new_character_len >= self.console.width: # We need to wrap here
|
||||||
|
new_screen[-1] += '\\'
|
||||||
|
self.screeninfo[-1][1].append(1)
|
||||||
|
new_screen.append(self.buffer[-1])
|
||||||
|
self.screeninfo.append((0, [new_character_len]))
|
||||||
|
else:
|
||||||
|
new_screen[-1] += self.buffer[-1]
|
||||||
|
self.screeninfo[-1][1].append(new_character_len)
|
||||||
|
self.cxy = self.pos2xy()
|
||||||
|
|
||||||
|
# Reset the function that is used for completing the screen
|
||||||
|
self.calc_screen = self.calc_complete_screen
|
||||||
|
return new_screen
|
||||||
|
|
||||||
|
def calc_complete_screen(self) -> list[str]:
|
||||||
"""The purpose of this method is to translate changes in
|
"""The purpose of this method is to translate changes in
|
||||||
self.buffer into changes in self.screen. Currently it rips
|
self.buffer into changes in self.screen. Currently it rips
|
||||||
everything down and starts from scratch, which whilst not
|
everything down and starts from scratch, which whilst not
|
||||||
|
@ -563,8 +589,8 @@ class Reader:
|
||||||
def refresh(self) -> None:
|
def refresh(self) -> None:
|
||||||
"""Recalculate and refresh the screen."""
|
"""Recalculate and refresh the screen."""
|
||||||
# this call sets up self.cxy, so call it first.
|
# this call sets up self.cxy, so call it first.
|
||||||
screen = self.calc_screen()
|
self.screen = self.calc_screen()
|
||||||
self.console.refresh(screen, self.cxy)
|
self.console.refresh(self.screen, self.cxy)
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
|
|
||||||
def do_cmd(self, cmd: tuple[str, list[str]]) -> None:
|
def do_cmd(self, cmd: tuple[str, list[str]]) -> None:
|
||||||
|
|
|
@ -283,7 +283,7 @@ class UnixConsole(Console):
|
||||||
|
|
||||||
self.__show_cursor()
|
self.__show_cursor()
|
||||||
|
|
||||||
self.screen = screen
|
self.screen = screen.copy()
|
||||||
self.move_cursor(cx, cy)
|
self.move_cursor(cx, cy)
|
||||||
self.flushoutput()
|
self.flushoutput()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue