mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	[3.13] gh-120041: Do not use append_to_screen when completions are visible (GH-120042) (#120051)
* gh-120041: Do not use append_to_screen when completions are visible (GH-120042) (cherry picked from commit8fc7653766) * gh-120041: Refactor check for visible completion menu in completing_reader (GH-120055) (cherry picked from commitbf8e5e53d0) --------- Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
This commit is contained in:
		
							parent
							
								
									2acbdc23ad
								
							
						
					
					
						commit
						8d74eae4d4
					
				
					 3 changed files with 52 additions and 10 deletions
				
			
		|  | @ -187,13 +187,15 @@ 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_visible: |  | ||||||
|                 r.cmpltn_menu_visible = True |                 r.cmpltn_menu_visible = True | ||||||
|  |                 r.cmpltn_message_visible = False | ||||||
|                 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) | ||||||
|                 r.dirty = True |                 r.dirty = True | ||||||
|             elif stem + p in completions: |             elif not r.cmpltn_menu_visible: | ||||||
|  |                 r.cmpltn_message_visible = True | ||||||
|  |                 if stem + p in completions: | ||||||
|                     r.msg = "[ complete but not unique ]" |                     r.msg = "[ complete but not unique ]" | ||||||
|                     r.dirty = True |                     r.dirty = True | ||||||
|                 else: |                 else: | ||||||
|  | @ -208,6 +210,9 @@ def do(self) -> None: | ||||||
| 
 | 
 | ||||||
|         commands.self_insert.do(self) |         commands.self_insert.do(self) | ||||||
| 
 | 
 | ||||||
|  |         if r.cmpltn_menu_visible or r.cmpltn_message_visible: | ||||||
|  |             r.calc_screen = r.calc_complete_screen | ||||||
|  | 
 | ||||||
|         if r.cmpltn_menu_visible: |         if r.cmpltn_menu_visible: | ||||||
|             stem = r.get_stem() |             stem = r.get_stem() | ||||||
|             if len(stem) < 1: |             if len(stem) < 1: | ||||||
|  | @ -236,6 +241,7 @@ class CompletingReader(Reader): | ||||||
|     ### Instance variables |     ### Instance variables | ||||||
|     cmpltn_menu: list[str] = field(init=False) |     cmpltn_menu: list[str] = field(init=False) | ||||||
|     cmpltn_menu_visible: bool = field(init=False) |     cmpltn_menu_visible: bool = field(init=False) | ||||||
|  |     cmpltn_message_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) | ||||||
| 
 | 
 | ||||||
|  | @ -271,6 +277,7 @@ def finish(self) -> None: | ||||||
|     def cmpltn_reset(self) -> None: |     def cmpltn_reset(self) -> None: | ||||||
|         self.cmpltn_menu = [] |         self.cmpltn_menu = [] | ||||||
|         self.cmpltn_menu_visible = False |         self.cmpltn_menu_visible = False | ||||||
|  |         self.cmpltn_message_visible = False | ||||||
|         self.cmpltn_menu_end = 0 |         self.cmpltn_menu_end = 0 | ||||||
|         self.cmpltn_menu_choices = [] |         self.cmpltn_menu_choices = [] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ def code_to_events(code: str): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def prepare_reader(console: Console, **kwargs): | def prepare_reader(console: Console, **kwargs): | ||||||
|     config = ReadlineConfig(readline_completer=None) |     config = ReadlineConfig(readline_completer=kwargs.pop("readline_completer", None)) | ||||||
|     reader = ReadlineAlikeReader(console=console, config=config) |     reader = ReadlineAlikeReader(console=console, config=config) | ||||||
|     reader.more_lines = partial(more_lines, namespace=None) |     reader.more_lines = partial(more_lines, namespace=None) | ||||||
|     reader.paste_mode = True  # Avoid extra indents |     reader.paste_mode = True  # Avoid extra indents | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| import itertools | import itertools | ||||||
| import functools | import functools | ||||||
|  | import rlcompleter | ||||||
| from unittest import TestCase | from unittest import TestCase | ||||||
| 
 | 
 | ||||||
| from .support import handle_all_events, handle_events_narrow_console, code_to_events, prepare_reader | from .support import handle_all_events, handle_events_narrow_console, code_to_events, prepare_reader | ||||||
|  | @ -9,7 +10,7 @@ | ||||||
| 
 | 
 | ||||||
| class TestReader(TestCase): | class TestReader(TestCase): | ||||||
|     def assert_screen_equals(self, reader, expected): |     def assert_screen_equals(self, reader, expected): | ||||||
|         actual = reader.calc_screen() |         actual = reader.screen | ||||||
|         expected = expected.split("\n") |         expected = expected.split("\n") | ||||||
|         self.assertListEqual(actual, expected) |         self.assertListEqual(actual, expected) | ||||||
| 
 | 
 | ||||||
|  | @ -208,3 +209,37 @@ def test_prompt_length(self): | ||||||
|         prompt, l = Reader.process_prompt(ps1) |         prompt, l = Reader.process_prompt(ps1) | ||||||
|         self.assertEqual(prompt, "\033[0;32m樂>\033[0m> ") |         self.assertEqual(prompt, "\033[0;32m樂>\033[0m> ") | ||||||
|         self.assertEqual(l, 5) |         self.assertEqual(l, 5) | ||||||
|  | 
 | ||||||
|  |     def test_completions_updated_on_key_press(self): | ||||||
|  |         namespace = {"itertools": itertools} | ||||||
|  |         code = "itertools." | ||||||
|  |         events = itertools.chain(code_to_events(code), [ | ||||||
|  |             Event(evt='key', data='\t', raw=bytearray(b'\t')),  # Two tabs for completion | ||||||
|  |             Event(evt='key', data='\t', raw=bytearray(b'\t')), | ||||||
|  |         ], code_to_events("a")) | ||||||
|  | 
 | ||||||
|  |         completing_reader = functools.partial( | ||||||
|  |             prepare_reader, | ||||||
|  |             readline_completer=rlcompleter.Completer(namespace).complete | ||||||
|  |         ) | ||||||
|  |         reader, _ = handle_all_events(events, prepare_reader=completing_reader) | ||||||
|  | 
 | ||||||
|  |         actual = reader.screen | ||||||
|  |         self.assertEqual(len(actual), 2) | ||||||
|  |         self.assertEqual(actual[0].rstrip(), "itertools.accumulate(") | ||||||
|  |         self.assertEqual(actual[1], f"{code}a") | ||||||
|  | 
 | ||||||
|  |     def test_key_press_on_tab_press_once(self): | ||||||
|  |         namespace = {"itertools": itertools} | ||||||
|  |         code = "itertools." | ||||||
|  |         events = itertools.chain(code_to_events(code), [ | ||||||
|  |             Event(evt='key', data='\t', raw=bytearray(b'\t')), | ||||||
|  |         ], code_to_events("a")) | ||||||
|  | 
 | ||||||
|  |         completing_reader = functools.partial( | ||||||
|  |             prepare_reader, | ||||||
|  |             readline_completer=rlcompleter.Completer(namespace).complete | ||||||
|  |         ) | ||||||
|  |         reader, _ = handle_all_events(events, prepare_reader=completing_reader) | ||||||
|  | 
 | ||||||
|  |         self.assert_screen_equals(reader, f"{code}a") | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miss Islington (bot)
						Miss Islington (bot)