mirror of
				https://github.com/python/cpython.git
				synced 2025-11-01 06:01:29 +00:00 
			
		
		
		
	gh-111201: Add append to screen method to avoid recalculation (#119274)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
		
							parent
							
								
									d065edfb66
								
							
						
					
					
						commit
						c886bece3b
					
				
					 4 changed files with 43 additions and 14 deletions
				
			
		|  | @ -358,7 +358,10 @@ def do(self) -> None: | ||||||
| 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 @@ def do(self) -> None: | ||||||
|             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 @@ def do(self) -> None: | ||||||
| 
 | 
 | ||||||
|         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 @@ def after_command(self, cmd: Command) -> None: | ||||||
|         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 @@ def finish(self) -> None: | ||||||
| 
 | 
 | ||||||
|     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 @@ | ||||||
| # 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 @@ def __post_init__(self) -> None: | ||||||
|         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 @@ def update_screen(self) -> None: | ||||||
|     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: | ||||||
|  |  | ||||||
|  | @ -293,7 +293,7 @@ def refresh(self, screen, c_xy): | ||||||
| 
 | 
 | ||||||
|         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
	
	 Lysandros Nikolaou
						Lysandros Nikolaou