diff options
| author | kobarity | 2024-02-24 23:11:02 +0900 |
|---|---|---|
| committer | Stefan Kangas | 2024-05-18 22:22:34 +0200 |
| commit | c97e7a2da2e5707fc94c2c5e2ddd5f2395cdb80b (patch) | |
| tree | c63927620fc855bd3c4c36c09890fffb318e1234 | |
| parent | bbb3038ad9feb1f37e4bef7151b2bc6f18c4123d (diff) | |
| download | emacs-c97e7a2da2e5707fc94c2c5e2ddd5f2395cdb80b.tar.gz emacs-c97e7a2da2e5707fc94c2c5e2ddd5f2395cdb80b.zip | |
Improve fontification of Python assignments with type hints
* lisp/progmodes/python.el (python-font-lock-keywords-maximum-decoration):
Fontify type hints of assignment statement. (Bug#69357)
* test/lisp/progmodes/python-tests.el
(python-font-lock-assignment-statement-11)
(python-font-lock-assignment-statement-12)
(python-font-lock-assignment-statement-13)
(python-font-lock-assignment-statement-18): Add fontification of type
hints.
(python-font-lock-assignment-statement-19): New test.
| -rw-r--r-- | lisp/progmodes/python.el | 31 | ||||
| -rw-r--r-- | test/lisp/progmodes/python-tests.el | 20 |
2 files changed, 39 insertions, 12 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 831bec7f4af..360936c9efd 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -794,6 +794,25 @@ sign in chained assignment." | |||
| 794 | ) | 794 | ) |
| 795 | symbol-end) | 795 | symbol-end) |
| 796 | . font-lock-type-face) | 796 | . font-lock-type-face) |
| 797 | ;; single assignment with/without type hints, e.g. | ||
| 798 | ;; a: int = 5 | ||
| 799 | ;; b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo') | ||
| 800 | ;; c: Collection = {1, 2, 3} | ||
| 801 | ;; d: Mapping[int, str] = {1: 'bar', 2: 'baz'} | ||
| 802 | (,(python-font-lock-assignment-matcher | ||
| 803 | (python-rx (or line-start ?\;) (* space) | ||
| 804 | grouped-assignment-target (* space) | ||
| 805 | (? ?: (* space) (group (+ not-simple-operator)) (* space)) | ||
| 806 | (group assignment-operator))) | ||
| 807 | (1 font-lock-variable-name-face) | ||
| 808 | (3 'font-lock-operator-face) | ||
| 809 | (,(python-rx symbol-name) | ||
| 810 | (progn | ||
| 811 | (when-let ((type-start (match-beginning 2))) | ||
| 812 | (goto-char type-start)) | ||
| 813 | (match-end 0)) | ||
| 814 | nil | ||
| 815 | (0 font-lock-type-face))) | ||
| 797 | ;; multiple assignment | 816 | ;; multiple assignment |
| 798 | ;; (note that type hints are not allowed for multiple assignments) | 817 | ;; (note that type hints are not allowed for multiple assignments) |
| 799 | ;; a, b, c = 1, 2, 3 | 818 | ;; a, b, c = 1, 2, 3 |
| @@ -826,18 +845,6 @@ sign in chained assignment." | |||
| 826 | (match-beginning 2)) ; limit the search until the assignment | 845 | (match-beginning 2)) ; limit the search until the assignment |
| 827 | nil | 846 | nil |
| 828 | (1 font-lock-variable-name-face))) | 847 | (1 font-lock-variable-name-face))) |
| 829 | ;; single assignment with type hints, e.g. | ||
| 830 | ;; a: int = 5 | ||
| 831 | ;; b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo') | ||
| 832 | ;; c: Collection = {1, 2, 3} | ||
| 833 | ;; d: Mapping[int, str] = {1: 'bar', 2: 'baz'} | ||
| 834 | (,(python-font-lock-assignment-matcher | ||
| 835 | (python-rx (or line-start ?\;) (* space) | ||
| 836 | grouped-assignment-target (* space) | ||
| 837 | (? ?: (* space) (+ not-simple-operator) (* space)) | ||
| 838 | (group assignment-operator))) | ||
| 839 | (1 font-lock-variable-name-face) | ||
| 840 | (2 'font-lock-operator-face)) | ||
| 841 | ;; special cases | 848 | ;; special cases |
| 842 | ;; (a) = 5 | 849 | ;; (a) = 5 |
| 843 | ;; [a] = 5, | 850 | ;; [a] = 5, |
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index f50797953c3..2960cca2c06 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el | |||
| @@ -391,7 +391,11 @@ p = (1 + 2) | |||
| 391 | (python-tests-assert-faces | 391 | (python-tests-assert-faces |
| 392 | "b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo')" | 392 | "b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo')" |
| 393 | '((1 . font-lock-variable-name-face) (2) | 393 | '((1 . font-lock-variable-name-face) (2) |
| 394 | (4 . font-lock-type-face) (9) | ||
| 395 | (10 . font-lock-type-face) (18) | ||
| 394 | (19 . font-lock-builtin-face) (22) | 396 | (19 . font-lock-builtin-face) (22) |
| 397 | (25 . font-lock-type-face) (30) | ||
| 398 | (31 . font-lock-type-face) (39) | ||
| 395 | (40 . font-lock-builtin-face) (43) | 399 | (40 . font-lock-builtin-face) (43) |
| 396 | (46 . font-lock-builtin-face) (49) | 400 | (46 . font-lock-builtin-face) (49) |
| 397 | (52 . font-lock-operator-face) (53) | 401 | (52 . font-lock-operator-face) (53) |
| @@ -402,12 +406,14 @@ p = (1 + 2) | |||
| 402 | (python-tests-assert-faces | 406 | (python-tests-assert-faces |
| 403 | "c: Collection = {1, 2, 3}" | 407 | "c: Collection = {1, 2, 3}" |
| 404 | '((1 . font-lock-variable-name-face) (2) | 408 | '((1 . font-lock-variable-name-face) (2) |
| 409 | (4 . font-lock-type-face) (14) | ||
| 405 | (15 . font-lock-operator-face) (16)))) | 410 | (15 . font-lock-operator-face) (16)))) |
| 406 | 411 | ||
| 407 | (ert-deftest python-font-lock-assignment-statement-13 () | 412 | (ert-deftest python-font-lock-assignment-statement-13 () |
| 408 | (python-tests-assert-faces | 413 | (python-tests-assert-faces |
| 409 | "d: Mapping[int, str] = {1: 'bar', 2: 'baz'}" | 414 | "d: Mapping[int, str] = {1: 'bar', 2: 'baz'}" |
| 410 | '((1 . font-lock-variable-name-face) (2) | 415 | '((1 . font-lock-variable-name-face) (2) |
| 416 | (4 . font-lock-type-face) (11) | ||
| 411 | (12 . font-lock-builtin-face) (15) | 417 | (12 . font-lock-builtin-face) (15) |
| 412 | (17 . font-lock-builtin-face) (20) | 418 | (17 . font-lock-builtin-face) (20) |
| 413 | (22 . font-lock-operator-face) (23) | 419 | (22 . font-lock-operator-face) (23) |
| @@ -472,14 +478,28 @@ def f(x: CustomInt) -> CustomInt: | |||
| 472 | (58 . font-lock-operator-face) (59) | 478 | (58 . font-lock-operator-face) (59) |
| 473 | (62 . font-lock-operator-face) (63) | 479 | (62 . font-lock-operator-face) (63) |
| 474 | (70 . font-lock-variable-name-face) (72) | 480 | (70 . font-lock-variable-name-face) (72) |
| 481 | (74 . font-lock-type-face) (82) | ||
| 482 | (83 . font-lock-type-face) (92) | ||
| 475 | (94 . font-lock-operator-face) (95) | 483 | (94 . font-lock-operator-face) (95) |
| 476 | (102 . font-lock-operator-face) (103) | 484 | (102 . font-lock-operator-face) (103) |
| 477 | (111 . font-lock-variable-name-face) (114) | 485 | (111 . font-lock-variable-name-face) (114) |
| 486 | (116 . font-lock-type-face) (125) | ||
| 478 | (126 . font-lock-operator-face) (127) | 487 | (126 . font-lock-operator-face) (127) |
| 479 | (128 . font-lock-builtin-face) (131) | 488 | (128 . font-lock-builtin-face) (131) |
| 480 | (136 . font-lock-operator-face) (137) | 489 | (136 . font-lock-operator-face) (137) |
| 481 | (144 . font-lock-keyword-face) (150)))) | 490 | (144 . font-lock-keyword-face) (150)))) |
| 482 | 491 | ||
| 492 | (ert-deftest python-font-lock-assignment-statement-19 () | ||
| 493 | (python-tests-assert-faces | ||
| 494 | "a: List[List[CustomInt], List[CustomInt]] = []" | ||
| 495 | '((1 . font-lock-variable-name-face) (2) | ||
| 496 | (4 . font-lock-type-face) (8) | ||
| 497 | (9 . font-lock-type-face) (13) | ||
| 498 | (14 . font-lock-type-face) (23) | ||
| 499 | (26 . font-lock-type-face) (30) | ||
| 500 | (31 . font-lock-type-face) (40) | ||
| 501 | (43 . font-lock-operator-face) (44)))) | ||
| 502 | |||
| 483 | (ert-deftest python-font-lock-operator-1 () | 503 | (ert-deftest python-font-lock-operator-1 () |
| 484 | (python-tests-assert-faces | 504 | (python-tests-assert-faces |
| 485 | "1 << 2 ** 3 == +4%-5|~6&7^8%9" | 505 | "1 << 2 ** 3 == +4%-5|~6&7^8%9" |