mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-118878: Pyrepl: show completions menu below the current line (#118939)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
This commit is contained in:
		
							parent
							
								
									5a9afe2362
								
							
						
					
					
						commit
						29caec62ee
					
				
					 5 changed files with 17 additions and 9 deletions
				
			
		|  | @ -282,7 +282,7 @@ def do(self) -> None: | ||||||
|             x, y = r.pos2xy() |             x, y = r.pos2xy() | ||||||
|             new_y = y + 1 |             new_y = y + 1 | ||||||
| 
 | 
 | ||||||
|             if new_y > r.max_row(): |             if r.eol() == len(b): | ||||||
|                 if r.historyi < len(r.history): |                 if r.historyi < len(r.history): | ||||||
|                     r.select_item(r.historyi + 1) |                     r.select_item(r.historyi + 1) | ||||||
|                     r.pos = r.eol(0) |                     r.pos = r.eol(0) | ||||||
|  | @ -309,7 +309,7 @@ def do(self) -> None: | ||||||
| class left(MotionCommand): | class left(MotionCommand): | ||||||
|     def do(self) -> None: |     def do(self) -> None: | ||||||
|         r = self.reader |         r = self.reader | ||||||
|         for i in range(r.get_arg()): |         for _ in range(r.get_arg()): | ||||||
|             p = r.pos - 1 |             p = r.pos - 1 | ||||||
|             if p >= 0: |             if p >= 0: | ||||||
|                 r.pos = p |                 r.pos = p | ||||||
|  | @ -321,7 +321,7 @@ class right(MotionCommand): | ||||||
|     def do(self) -> None: |     def do(self) -> None: | ||||||
|         r = self.reader |         r = self.reader | ||||||
|         b = r.buffer |         b = r.buffer | ||||||
|         for i in range(r.get_arg()): |         for _ in range(r.get_arg()): | ||||||
|             p = r.pos + 1 |             p = r.pos + 1 | ||||||
|             if p <= len(b): |             if p <= len(b): | ||||||
|                 r.pos = p |                 r.pos = p | ||||||
|  |  | ||||||
|  | @ -260,10 +260,15 @@ def after_command(self, cmd: Command) -> None: | ||||||
|     def calc_screen(self) -> list[str]: |     def calc_screen(self) -> list[str]: | ||||||
|         screen = super().calc_screen() |         screen = super().calc_screen() | ||||||
|         if self.cmpltn_menu_visible: |         if self.cmpltn_menu_visible: | ||||||
|             ly = self.lxy[1] |             # We display the completions menu below the current prompt | ||||||
|  |             ly = self.lxy[1] + 1 | ||||||
|             screen[ly:ly] = self.cmpltn_menu |             screen[ly:ly] = self.cmpltn_menu | ||||||
|             self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu) |             # If we're not in the middle of multiline edit, don't append to screeninfo | ||||||
|             self.cxy = self.cxy[0], self.cxy[1] + len(self.cmpltn_menu) |             # since that screws up the position calculation in pos2xy function. | ||||||
|  |             # This is a hack to prevent the cursor jumping | ||||||
|  |             # into the completions menu when pressing left or down arrow. | ||||||
|  |             if self.pos != len(self.buffer): | ||||||
|  |                 self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu) | ||||||
|         return screen |         return screen | ||||||
| 
 | 
 | ||||||
|     def finish(self) -> None: |     def finish(self) -> None: | ||||||
|  |  | ||||||
|  | @ -850,7 +850,7 @@ def test_global_namespace_completion(self): | ||||||
|         output = multiline_input(reader, namespace) |         output = multiline_input(reader, namespace) | ||||||
|         self.assertEqual(output, "python") |         self.assertEqual(output, "python") | ||||||
| 
 | 
 | ||||||
|     def test_updown_arrow_with_completion_menu(self): |     def test_up_down_arrow_with_completion_menu(self): | ||||||
|         """Up arrow in the middle of unfinished tab completion when the menu is displayed |         """Up arrow in the middle of unfinished tab completion when the menu is displayed | ||||||
|         should work and trigger going back in history. Down arrow should subsequently |         should work and trigger going back in history. Down arrow should subsequently | ||||||
|         get us back to the incomplete command.""" |         get us back to the incomplete command.""" | ||||||
|  | @ -860,6 +860,7 @@ def test_updown_arrow_with_completion_menu(self): | ||||||
|         events = itertools.chain( |         events = itertools.chain( | ||||||
|             code_to_events(code), |             code_to_events(code), | ||||||
|             [ |             [ | ||||||
|  |                 Event(evt="key", data="down", raw=bytearray(b"\x1bOB")), | ||||||
|                 Event(evt="key", data="up", raw=bytearray(b"\x1bOA")), |                 Event(evt="key", data="up", raw=bytearray(b"\x1bOA")), | ||||||
|                 Event(evt="key", data="down", raw=bytearray(b"\x1bOB")), |                 Event(evt="key", data="down", raw=bytearray(b"\x1bOB")), | ||||||
|             ], |             ], | ||||||
|  |  | ||||||
|  | @ -295,8 +295,8 @@ def test_completions_updated_on_key_press(self): | ||||||
| 
 | 
 | ||||||
|         actual = reader.screen |         actual = reader.screen | ||||||
|         self.assertEqual(len(actual), 2) |         self.assertEqual(len(actual), 2) | ||||||
|         self.assertEqual(actual[0].rstrip(), "itertools.accumulate(") |         self.assertEqual(actual[0], f"{code}a") | ||||||
|         self.assertEqual(actual[1], f"{code}a") |         self.assertEqual(actual[1].rstrip(), "itertools.accumulate(") | ||||||
| 
 | 
 | ||||||
|     def test_key_press_on_tab_press_once(self): |     def test_key_press_on_tab_press_once(self): | ||||||
|         namespace = {"itertools": itertools} |         namespace = {"itertools": itertools} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | Show tab completions menu below the current line, which results in less | ||||||
|  | janky behaviour, and fixes a cursor movement bug. Patch by Daniel Hollas | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Daniel Hollas
						Daniel Hollas