aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorLaurence Warne2022-08-09 08:33:18 +0100
committerLars Ingebrigtsen2022-08-09 19:21:36 +0200
commitb92e88875802724af9e08201ea65a96dd5f20ff1 (patch)
tree9a0136781ddab7618c4752d60c1c84830a07d95a /lisp/progmodes/python.el
parent3ef18c7a213f4f3c03eec033fcb8219fb17cd53d (diff)
downloademacs-b92e88875802724af9e08201ea65a96dd5f20ff1.tar.gz
emacs-b92e88875802724af9e08201ea65a96dd5f20ff1.zip
Fix python escape code fontification for multi-line literals
* lisp/progmodes/python.el (python--string-bytes-literal-matcher): Go backward one char after a match so that consecutive escape codes are highlighted (python--not-raw-string-literal-start-regexp): Make regular expression more comprehensive, so multi-line bytes literals are not caught (python-rx): Accept one to three octal digits in octal escape codes instead of always three
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el22
1 files changed, 15 insertions, 7 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 5edd6e7df56..96f9d14832d 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -432,7 +432,7 @@ This variant of `rx' supports common Python named REGEXPS."
432 (seq (not "\\") 432 (seq (not "\\")
433 (group (or "\\\\" "\\'" "\\a" "\\b" "\\f" 433 (group (or "\\\\" "\\'" "\\a" "\\b" "\\f"
434 "\\n" "\\r" "\\t" "\\v" 434 "\\n" "\\r" "\\t" "\\v"
435 (seq "\\" (= 3 (in "0-7"))) 435 (seq "\\" (** 1 3 (in "0-7")))
436 (seq "\\x" hex hex))))) 436 (seq "\\x" hex hex)))))
437 (string-escape-sequence 437 (string-escape-sequence
438 (or bytes-escape-sequence 438 (or bytes-escape-sequence
@@ -556,7 +556,14 @@ the {...} holes that appear within f-strings."
556 "A regular expression matching the start of a not-raw bytes literal.") 556 "A regular expression matching the start of a not-raw bytes literal.")
557 557
558(defconst python--not-raw-string-literal-start-regexp 558(defconst python--not-raw-string-literal-start-regexp
559 (rx (or bos (not alnum)) (? (or "u" "U" "F" "f")) (or "\"" "\"\"\"" "'" "'''") eos) 559 (rx bos (or
560 ;; Multi-line string literals
561 (seq (? (? (not alnum)) (or "u" "U" "F" "f")) (or "\"\"\"" "'''"))
562 (seq (? anychar) (not alnum) (or "\"\"\"" "'''"))
563 ;; Single line string literals
564 (seq (? (** 0 2 anychar) (not alnum)) (or "u" "U" "F" "f") (or "'" "\""))
565 (seq (? (** 0 3 anychar) (not (any "'\"" alnum))) (or "'" "\"")))
566 eos)
560 "A regular expression matching the start of a not-raw string literal.") 567 "A regular expression matching the start of a not-raw string literal.")
561 568
562(defun python--string-bytes-literal-matcher (regexp start-regexp) 569(defun python--string-bytes-literal-matcher (regexp start-regexp)
@@ -565,11 +572,12 @@ the {...} holes that appear within f-strings."
565 (cl-loop for result = (re-search-forward regexp limit t) 572 (cl-loop for result = (re-search-forward regexp limit t)
566 for result-valid = (and 573 for result-valid = (and
567 result 574 result
568 (let* ((pos (nth 8 (syntax-ppss))) 575 (when-let* ((pos (nth 8 (syntax-ppss)))
569 (before-quote 576 (before-quote
570 (buffer-substring-no-properties 577 (buffer-substring-no-properties
571 (max (- pos 5) (point-min)) 578 (max (- pos 4) (point-min))
572 (min (+ pos 1) (point-max))))) 579 (min (+ pos 1) (point-max)))))
580 (backward-char)
573 (string-match-p start-regexp before-quote))) 581 (string-match-p start-regexp before-quote)))
574 until (or (not result) result-valid) 582 until (or (not result) result-valid)
575 finally return (and result-valid result)))) 583 finally return (and result-valid result))))