|
4 | 4 | from textwrap import dedent
|
5 | 5 | from unittest import TestCase
|
6 | 6 | from unittest.mock import MagicMock
|
| 7 | +from _pyrepl.readline import multiline_input |
7 | 8 | from test.support import force_colorized_test_class, force_not_colorized_test_class
|
8 | 9 |
|
9 | 10 | from .support import handle_all_events, handle_events_narrow_console
|
@@ -358,6 +359,59 @@ def test_setpos_from_xy_for_non_printing_char(self):
|
358 | 359 | reader.setpos_from_xy(8, 0)
|
359 | 360 | self.assertEqual(reader.pos, 7)
|
360 | 361 |
|
| 362 | + def test_empty_line_control_w_k(self): |
| 363 | + """Test that Control-W followed by Control-K on an empty line doesn't crash.""" |
| 364 | + events = itertools.chain( |
| 365 | + [ |
| 366 | + Event(evt="key", data="\x17", raw=bytearray(b"\x17")), # Control-W |
| 367 | + Event(evt="key", data="\x0b", raw=bytearray(b"\x0b")), # Control-K |
| 368 | + ], |
| 369 | + ) |
| 370 | + reader, _ = handle_all_events(events) |
| 371 | + self.assert_screen_equal(reader, "", clean=True) |
| 372 | + self.assertEqual(reader.pos, 0) |
| 373 | + |
| 374 | + def test_control_w_delete_word(self): |
| 375 | + """Test Control-W delete word""" |
| 376 | + def test_with_text(text: str, expected: list[str], before_pos: int, after_pos: int): |
| 377 | + events = itertools.chain( |
| 378 | + code_to_events(text) if len(text) else [], |
| 379 | + [Event(evt="key", data="left", raw=bytearray(b"\x1b[D"))] * (len(text) - before_pos), # Move cursor to specified position |
| 380 | + [ |
| 381 | + Event(evt="key", data="\x17", raw=bytearray(b"\x17")), # Control-W |
| 382 | + ], |
| 383 | + ) |
| 384 | + reader, _ = handle_all_events(events) |
| 385 | + self.assertEqual(reader.screen, expected) |
| 386 | + self.assertEqual(reader.pos, after_pos) |
| 387 | + |
| 388 | + test_with_text("", [], 0, 0) |
| 389 | + test_with_text("a", [""], 1, 0) |
| 390 | + test_with_text("abc", [""], 3, 0) |
| 391 | + test_with_text("abc def", ["def"], 4, 0) |
| 392 | + test_with_text("abc def", ["abc "], 7, 4) |
| 393 | + test_with_text("def xxx():xxx\n ", ["def xxx():"], 18, 10) |
| 394 | + |
| 395 | + def test_control_k_delete_to_eol(self): |
| 396 | + """Test Control-K delete from cursor to end of line""" |
| 397 | + def test_with_text(text: str, pos: int, expected: list[str]): |
| 398 | + events = itertools.chain( |
| 399 | + code_to_events(text) if len(text) else [], |
| 400 | + [Event(evt="key", data="left", raw=bytearray(b"\x1b[D"))] * (len(text) - pos), # Move cursor to specified position |
| 401 | + [ |
| 402 | + Event(evt="key", data="\x0b", raw=bytearray(b"\x0b")), # Control-K |
| 403 | + ], |
| 404 | + ) |
| 405 | + reader, _ = handle_all_events(events) |
| 406 | + self.assertEqual(reader.screen, expected) |
| 407 | + self.assertEqual(reader.pos, pos) |
| 408 | + |
| 409 | + test_with_text("", 0, [""]) |
| 410 | + test_with_text("a", 0, [""]) |
| 411 | + test_with_text("abc", 1, ["a"]) |
| 412 | + test_with_text("abc def", 4, ["abc "]) |
| 413 | + test_with_text("def xxx():xxx\n pass", 10, ["def xxx():", " pass"]) |
| 414 | + |
361 | 415 | @force_colorized_test_class
|
362 | 416 | class TestReaderInColor(ScreenEqualMixin, TestCase):
|
363 | 417 | def test_syntax_highlighting_basic(self):
|
|
0 commit comments