Commit 3b3274a8 authored by Stefan Monnier's avatar Stefan Monnier

* lisp/progmodes/python.el: Teach f-strings to `font-lock`

(python--f-string-p, python--font-lock-f-strings): New functions.
(python-font-lock-keywords-maximum-decoration): Use them.
parent c41c1ac4
Pipeline #7381 passed with stage
in 64 minutes and 28 seconds
......@@ -501,6 +501,52 @@ The type returned can be `comment', `string' or `paren'."
font-lock-string-face)
font-lock-comment-face))
(defun python--f-string-p (ppss)
"Return non-nil if the pos where PPSS was found is inside an f-string."
(and (nth 3 ppss)
(let ((spos (1- (nth 8 ppss))))
(and (memq (char-after spos) '(?f ?F))
(or (< (point-min) spos)
(not (memq (char-syntax (char-before spos)) '(?w ?_))))))))
(defun python--font-lock-f-strings (limit)
"Mark {...} holes as being code.
Remove the (presumably `font-lock-string-face') `face' property from
the {...} holes that appear within f-strings."
;; FIXME: This will fail to properly highlight strings appearing
;; within the {...} of an f-string.
;; We could presumably fix it by running
;; `font-lock-fontify-syntactically-region' (as is done in
;; `sm-c--cpp-fontify-syntactically', for example) after removing
;; the `face' property, but I'm not sure it's worth the effort and
;; the risks.
(let ((ppss (syntax-ppss)))
(while
(progn
(while (and (not (python--f-string-p ppss))
(re-search-forward "\\<f['\"]" limit 'move))
(setq ppss (syntax-ppss)))
(< (point) limit))
(cl-assert (python--f-string-p ppss))
(let ((send (save-excursion
(goto-char (nth 8 ppss))
(condition-case nil
(progn (let ((forward-sexp-function nil))
(forward-sexp 1))
(min limit (1- (point))))
(scan-error limit)))))
(while (re-search-forward "{" send t)
(if (eq ?\{ (char-after))
(forward-char 1) ;Just skip over {{
(let ((beg (match-beginning 0))
(end (condition-case nil
(progn (up-list 1) (min send (point)))
(scan-error send))))
(goto-char end)
(put-text-property beg end 'face nil))))
(goto-char (min limit (1+ send)))
(setq ppss (syntax-ppss))))))
(defvar python-font-lock-keywords-level-1
`((,(rx symbol-start "def" (1+ space) (group (1+ (or word ?_))))
(1 font-lock-function-name-face))
......@@ -567,7 +613,8 @@ This is the medium decoration level, including everything in
builtins.")
(defvar python-font-lock-keywords-maximum-decoration
`(,@python-font-lock-keywords-level-2
`((python--font-lock-f-strings)
,@python-font-lock-keywords-level-2
;; Constants
(,(rx symbol-start
(or
......@@ -575,7 +622,8 @@ builtins.")
;; copyright, license, credits, quit and exit are added by the site
;; module and they are not intended to be used in programs
"copyright" "credits" "exit" "license" "quit")
symbol-end) . font-lock-constant-face)
symbol-end)
. font-lock-constant-face)
;; Decorators.
(,(rx line-start (* (any " \t")) (group "@" (1+ (or word ?_))
(0+ "." (1+ (or word ?_)))))
......@@ -609,7 +657,8 @@ builtins.")
;; OS specific
"VMSError" "WindowsError"
)
symbol-end) . font-lock-type-face)
symbol-end)
. font-lock-type-face)
;; assignments
;; support for a = b = c = 5
(,(lambda (limit)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment