|
1 | 1 | import itertools |
2 | 2 | import functools |
3 | 3 | import rlcompleter |
| 4 | +from textwrap import dedent |
4 | 5 | from unittest import TestCase |
5 | 6 | from unittest.mock import MagicMock |
6 | 7 |
|
7 | 8 | from .support import handle_all_events, handle_events_narrow_console |
8 | 9 | from .support import ScreenEqualMixin, code_to_events |
9 | | -from .support import prepare_reader, prepare_console |
| 10 | +from .support import prepare_reader, prepare_console, reader_force_colors |
10 | 11 | from _pyrepl.console import Event |
11 | 12 | from _pyrepl.reader import Reader |
| 13 | +from _pyrepl.utils import TAG_TO_ANSI |
| 14 | + |
| 15 | + |
| 16 | +colors = {k[0].lower(): v for k, v in TAG_TO_ANSI.items() if k != "SYNC"} |
| 17 | +colors["z"] = TAG_TO_ANSI["SYNC"] |
12 | 18 |
|
13 | 19 |
|
14 | 20 | class TestReader(ScreenEqualMixin, TestCase): |
@@ -123,8 +129,9 @@ def test_setpos_for_xy_simple(self): |
123 | 129 | def test_control_characters(self): |
124 | 130 | code = 'flag = "🏳️🌈"' |
125 | 131 | events = code_to_events(code) |
126 | | - reader, _ = handle_all_events(events) |
| 132 | + reader, _ = handle_all_events(events, prepare_reader=reader_force_colors) |
127 | 133 | self.assert_screen_equal(reader, 'flag = "🏳️\\u200d🌈"', clean=True) |
| 134 | + self.assert_screen_equal(reader, 'flag = {s}"🏳️\\u200d🌈"{z}'.format(**colors)) |
128 | 135 |
|
129 | 136 | def test_setpos_from_xy_multiple_lines(self): |
130 | 137 | # fmt: off |
@@ -355,3 +362,60 @@ def test_setpos_from_xy_for_non_printing_char(self): |
355 | 362 | reader, _ = handle_all_events(events) |
356 | 363 | reader.setpos_from_xy(8, 0) |
357 | 364 | self.assertEqual(reader.pos, 7) |
| 365 | + |
| 366 | + def test_syntax_highlighting_basic(self): |
| 367 | + code = dedent( |
| 368 | + """\ |
| 369 | + import re, sys |
| 370 | + def funct(case: str = sys.platform) -> None: |
| 371 | + match = re.search( |
| 372 | + "(me)", |
| 373 | + ''' |
| 374 | + Come on |
| 375 | + Come on now |
| 376 | + You know that it's time to emerge |
| 377 | + ''', |
| 378 | + ) |
| 379 | + match case: |
| 380 | + case "emscripten": print("on the web") |
| 381 | + case "ios" | "android": print("on the phone") |
| 382 | + case _: print('arms around', match.group(1)) |
| 383 | + """ |
| 384 | + ) |
| 385 | + expected = dedent( |
| 386 | + """\ |
| 387 | + {k}import{z} re, sys |
| 388 | + {a}{k}def{z} {d}funct{z}(case: {b}str{z} = sys.platform) -> {k}None{z}: |
| 389 | + match = re.search( |
| 390 | + {s}"(me)"{z}, |
| 391 | + {s}'''{z} |
| 392 | + {s} Come on{z} |
| 393 | + {s} Come on now{z} |
| 394 | + {s} You know that it's time to emerge{z} |
| 395 | + {s} '''{z}, |
| 396 | + ) |
| 397 | + {k}match{z} case: |
| 398 | + {k}case{z} {s}"emscripten"{z}: {b}print{z}({s}"on the web"{z}) |
| 399 | + {k}case{z} {s}"ios"{z} | {s}"android"{z}: {b}print{z}({s}"on the phone"{z}) |
| 400 | + {k}case{z} {k}_{z}: {b}print{z}({s}'arms around'{z}, match.group(1)) |
| 401 | + """ |
| 402 | + ) |
| 403 | + expected_sync = expected.format(a="", **colors) |
| 404 | + events = code_to_events(code) |
| 405 | + reader, _ = handle_all_events(events, prepare_reader=reader_force_colors) |
| 406 | + self.assert_screen_equal(reader, code, clean=True) |
| 407 | + self.assert_screen_equal(reader, expected_sync) |
| 408 | + self.assertEqual(reader.pos, 2**7 + 2**8) |
| 409 | + self.assertEqual(reader.cxy, (0, 14)) |
| 410 | + |
| 411 | + async_msg = "{k}async{z} ".format(**colors) |
| 412 | + expected_async = expected.format(a=async_msg, **colors) |
| 413 | + more_events = itertools.chain( |
| 414 | + code_to_events(code), |
| 415 | + [Event(evt="key", data="up", raw=bytearray(b"\x1bOA"))] * 13, |
| 416 | + code_to_events("async "), |
| 417 | + ) |
| 418 | + reader, _ = handle_all_events(more_events, prepare_reader=reader_force_colors) |
| 419 | + self.assert_screen_equal(reader, expected_async) |
| 420 | + self.assertEqual(reader.pos, 21) |
| 421 | + self.assertEqual(reader.cxy, (6, 1)) |
0 commit comments