diff options
| -rw-r--r-- | lisp/progmodes/python.el | 17 | ||||
| -rw-r--r-- | test/lisp/progmodes/python-tests.el | 12 |
2 files changed, 22 insertions, 7 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 147c5f248d2..3247d7ad507 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -546,11 +546,22 @@ The type returned can be `comment', `string' or `paren'." | |||
| 546 | font-lock-string-face) | 546 | font-lock-string-face) |
| 547 | font-lock-comment-face)) | 547 | font-lock-comment-face)) |
| 548 | 548 | ||
| 549 | (defconst python--f-string-start-regexp | ||
| 550 | (rx bow | ||
| 551 | (or "f" "F" "fr" "Fr" "fR" "FR" "rf" "rF" "Rf" "RF") | ||
| 552 | (or "\"" "\"\"\"" "'" "'''")) | ||
| 553 | "A regular expression matching the beginning of an f-string. | ||
| 554 | |||
| 555 | See URL `https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals'.") | ||
| 556 | |||
| 549 | (defun python--f-string-p (ppss) | 557 | (defun python--f-string-p (ppss) |
| 550 | "Return non-nil if the pos where PPSS was found is inside an f-string." | 558 | "Return non-nil if the pos where PPSS was found is inside an f-string." |
| 551 | (and (nth 3 ppss) | 559 | (and (nth 3 ppss) |
| 552 | (let ((spos (1- (nth 8 ppss)))) | 560 | (let* ((spos (1- (nth 8 ppss))) |
| 553 | (and (memq (char-after spos) '(?f ?F)) | 561 | (before-quote |
| 562 | (buffer-substring-no-properties (max (- spos 4) (point-min)) | ||
| 563 | (min (+ spos 2) (point-max))))) | ||
| 564 | (and (string-match-p python--f-string-start-regexp before-quote) | ||
| 554 | (or (< (point-min) spos) | 565 | (or (< (point-min) spos) |
| 555 | (not (memq (char-syntax (char-before spos)) '(?w ?_)))))))) | 566 | (not (memq (char-syntax (char-before spos)) '(?w ?_)))))))) |
| 556 | 567 | ||
| @@ -569,7 +580,7 @@ the {...} holes that appear within f-strings." | |||
| 569 | (while | 580 | (while |
| 570 | (progn | 581 | (progn |
| 571 | (while (and (not (python--f-string-p ppss)) | 582 | (while (and (not (python--f-string-p ppss)) |
| 572 | (re-search-forward "\\<f['\"]" limit 'move)) | 583 | (re-search-forward python--f-string-start-regexp limit 'move)) |
| 573 | (setq ppss (syntax-ppss))) | 584 | (setq ppss (syntax-ppss))) |
| 574 | (< (point) limit)) | 585 | (< (point) limit)) |
| 575 | (cl-assert (python--f-string-p ppss)) | 586 | (cl-assert (python--f-string-p ppss)) |
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 906f7eca7de..20a7a0132a8 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el | |||
| @@ -574,10 +574,14 @@ u\"\\n\"" | |||
| 574 | (195 . font-lock-string-face) | 574 | (195 . font-lock-string-face) |
| 575 | (196 . font-lock-constant-face) | 575 | (196 . font-lock-constant-face) |
| 576 | (215 . font-lock-string-face) (218) | 576 | (215 . font-lock-string-face) (218) |
| 577 | (221 . font-lock-string-face) (274) | 577 | (221 . font-lock-string-face) (254) |
| 578 | (277 . font-lock-string-face) (330) | 578 | (271 . font-lock-string-face) (274) |
| 579 | (333 . font-lock-string-face) (386) | 579 | (277 . font-lock-string-face) (310) |
| 580 | (389 . font-lock-string-face) (442) | 580 | (327 . font-lock-string-face) (330) |
| 581 | (333 . font-lock-string-face) (366) | ||
| 582 | (383 . font-lock-string-face) (386) | ||
| 583 | (389 . font-lock-string-face) (422) | ||
| 584 | (439 . font-lock-string-face) (442) | ||
| 581 | (444 . font-lock-string-face) (497) | 585 | (444 . font-lock-string-face) (497) |
| 582 | (499 . font-lock-string-face) (552) | 586 | (499 . font-lock-string-face) (552) |
| 583 | (555 . font-lock-string-face) (608) | 587 | (555 . font-lock-string-face) (608) |