aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el96
1 files changed, 69 insertions, 27 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index d58b32f3c3c..50bb841111f 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -394,6 +394,12 @@ This variant of `rx' supports common Python named REGEXPS."
394 (any ?' ?\") "__main__" (any ?' ?\") 394 (any ?' ?\") "__main__" (any ?' ?\")
395 (* space) ?:)) 395 (* space) ?:))
396 (symbol-name (seq (any letter ?_) (* (any word ?_)))) 396 (symbol-name (seq (any letter ?_) (* (any word ?_))))
397 (assignment-target (seq (? ?*)
398 (* symbol-name ?.) symbol-name
399 (? ?\[ (+ (not ?\])) ?\])))
400 (grouped-assignment-target (seq (? ?*)
401 (* symbol-name ?.) (group symbol-name)
402 (? ?\[ (+ (not ?\])) ?\])))
397 (open-paren (or "{" "[" "(")) 403 (open-paren (or "{" "[" "("))
398 (close-paren (or "}" "]" ")")) 404 (close-paren (or "}" "]" ")"))
399 (simple-operator (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)) 405 (simple-operator (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))
@@ -605,6 +611,18 @@ This is the medium decoration level, including everything in
605`python-font-lock-keywords-level-1', as well as keywords and 611`python-font-lock-keywords-level-1', as well as keywords and
606builtins.") 612builtins.")
607 613
614(defun python-font-lock-assignment-matcher (regexp)
615 "Font lock matcher for assignments based on REGEXP.
616Return nil if REGEXP matched within a `paren' context (to avoid,
617e.g., default values for arguments or passing arguments by name
618being treated as assignments) or is followed by an '=' sign (to
619avoid '==' being treated as an assignment."
620 (lambda (limit)
621 (let ((res (re-search-forward regexp limit t)))
622 (unless (or (python-syntax-context 'paren)
623 (equal (char-after (point)) ?=))
624 res))))
625
608(defvar python-font-lock-keywords-maximum-decoration 626(defvar python-font-lock-keywords-maximum-decoration
609 `((python--font-lock-f-strings) 627 `((python--font-lock-f-strings)
610 ,@python-font-lock-keywords-level-2 628 ,@python-font-lock-keywords-level-2
@@ -652,33 +670,57 @@ builtins.")
652 ) 670 )
653 symbol-end) 671 symbol-end)
654 . font-lock-type-face) 672 . font-lock-type-face)
655 ;; assignments 673 ;; multiple assignment
656 ;; support for a = b = c = 5 674 ;; (note that type hints are not allowed for multiple assignments)
657 (,(lambda (limit) 675 ;; a, b, c = 1, 2, 3
658 (let ((re (python-rx (group symbol-name) 676 ;; a, *b, c = 1, 2, 3, 4, 5
659 ;; subscript, like "[5]" 677 ;; [a, b] = (1, 2)
660 (? ?\[ (+ (not ?\])) ?\]) (* space) 678 ;; (l[1], l[2]) = (10, 11)
661 ;; type hint, like ": int" or ": Mapping[int, str]" 679 ;; (a, b, c, *d) = *x, y = 5, 6, 7, 8, 9
662 (? ?: (* space) (+ not-simple-operator) (* space)) 680 ;; (a,) = 'foo'
663 assignment-operator)) 681 ;; (*a,) = ['foo', 'bar', 'baz']
664 (res nil)) 682 ;; d.x, d.y[0], *d.z = 'a', 'b', 'c', 'd', 'e'
665 (while (and (setq res (re-search-forward re limit t)) 683 ;; and variants thereof
666 (or (python-syntax-context 'paren) 684 ;; the cases
667 (equal (char-after (point)) ?=)))) 685 ;; (a) = 5
668 res)) 686 ;; [a] = 5
669 (1 font-lock-variable-name-face nil nil)) 687 ;; [*a] = 5, 6
670 ;; support for a, b, c = (1, 2, 3) 688 ;; are handled separately below
671 (,(lambda (limit) 689 (,(python-font-lock-assignment-matcher
672 (let ((re (python-rx (group symbol-name) (* space) 690 (python-rx (? (or "[" "(") (* space))
673 (* ?, (* space) symbol-name (* space)) 691 grouped-assignment-target (* space) ?, (* space)
674 ?, (* space) symbol-name (* space) 692 (* assignment-target (* space) ?, (* space))
675 assignment-operator)) 693 (? assignment-target (* space))
676 (res nil)) 694 (? ?, (* space))
677 (while (and (setq res (re-search-forward re limit t)) 695 (? (or ")" "]") (* space))
678 (goto-char (match-end 1)) 696 (group assignment-operator)))
679 (python-syntax-context 'paren))) 697 (1 font-lock-variable-name-face)
680 res)) 698 (,(python-rx grouped-assignment-target)
681 (1 font-lock-variable-name-face nil nil))) 699 (progn
700 (goto-char (match-end 1)) ; go back after the first symbol
701 (match-beginning 2)) ; limit the search until the assignment
702 nil
703 (1 font-lock-variable-name-face)))
704 ;; single assignment with type hints, e.g.
705 ;; a: int = 5
706 ;; b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo')
707 ;; c: Collection = {1, 2, 3}
708 ;; d: Mapping[int, str] = {1: 'bar', 2: 'baz'}
709 (,(python-font-lock-assignment-matcher
710 (python-rx grouped-assignment-target (* space)
711 (? ?: (* space) (+ not-simple-operator) (* space))
712 assignment-operator))
713 (1 font-lock-variable-name-face))
714 ;; special cases
715 ;; (a) = 5
716 ;; [a] = 5
717 ;; [*a] = 5, 6
718 (,(python-font-lock-assignment-matcher
719 (python-rx (or "[" "(") (* space)
720 grouped-assignment-target (* space)
721 (or ")" "]") (* space)
722 assignment-operator))
723 (1 font-lock-variable-name-face)))
682 "Font lock keywords to use in python-mode for maximum decoration. 724 "Font lock keywords to use in python-mode for maximum decoration.
683 725
684This decoration level includes everything in 726This decoration level includes everything in