10

Update, Emacs 28 supports f-stings


Python 3.6 supports F strings, eg:

So:

print(f'Test {} me!'.format(2 + 2))

Can be written as:

print(f'Test {2 + 2} me!')

Which print's Test 4 me, Is there a way to adjust emacs syntax highlighting so the text between the {...} shows using regular code syntax-highlighting (instead of the same highlighting as a string).

4

3 Answers 3

6

FWIW, I just pushed support for "proper" highlighting of f-strings in Emacs's master branch, so it will be available in Emacs-28 when that gets released (and is available in GNU ELPA's python package as of version 0.27, for older Emacsen).

2

The mentioned bug thread provides a workaround hack, which works on some simple cases. I extended that hack a bit, to better address my use cases:

(defconst brace-regexp
  "[^{]{[^{}]*}")
(defconst python-f-string-regexp
  "f\\('.*?[^\\]'\\|\".*?[^\\]\"\\)")
(defun python-f-string-font-lock-find (limit)
  (while (re-search-forward python-f-string-regexp limit t)
    (put-text-property (match-beginning 0) (match-end 0)
                       'face 'font-lock-string-face)
    (let ((start (match-beginning 0)))
      (while (re-search-backward brace-regexp start t)
        (put-text-property (1+ (match-beginning 0)) (match-end 0)
                           'face 'font-lock-type-face))))
  nil)
(with-eval-after-load 'python
  (font-lock-add-keywords
   'python-mode
   `((python-f-string-font-lock-find))
   'append))

Good stuff:

  • Only applied on f-strings, not on string literals. This is the main feature, it prevents real bugs by capturing visually when I forget to add the f.
  • works with (almost) arbitrary expressions within the {}
  • {{ does not trigger highlighting Bad stuff:
  • still hacky, I'm not elisp literate
  • if the expression within {} contains a }, then expression highlight will be cut off there
  • expressions within {} get all the same colour (I arbitrarily picked the 'type' face because it contrasts well with strings on my system)
0

Try https://github.com/karlotness/tree-sitter.el , works perfectly for me.

;; Core APIs.
(straight-register-package
 '(tsc :host github
       :repo "ubolonton/emacs-tree-sitter"
       :files ("core/*.el")))

;; Base framework, syntax highlighting.
(use-package tree-sitter
  :straight (:host github
                   :repo "ubolonton/emacs-tree-sitter"
                   :files ("lisp/*.el"))
  :diminish (tree-sitter-mode)
  :hook ((after-init . global-tree-sitter-mode)
         (tree-sitter-after-on . tree-sitter-hl-mode)))

;; Language bundle.
(use-package tree-sitter-langs
  :straight (:host github
                   :repo "ubolonton/emacs-tree-sitter"
                   :files ("langs/*.el" "langs/queries"))
  :demand t
  :after tree-sitter)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.