[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:
Miss Islington (bot) 2024-05-22 18:03:04 +02:00 committed by GitHub
parent ac9163637b
commit aefe2e626e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 43 additions and 14 deletions

View file

@ -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):

View file

@ -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 = []

View file

@ -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:

View file

@ -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()