Search code examples
emacselispfont-lockemacs-faces

Emacs syntax highlighting of optional parts


I'm trying to write a derived mode from fundamental-mode. Assuming that I have this regexp : A ((foo)bar)? B, how can I tell emacs to use the following faces ?

  • font-lock-keyword-face on A
  • font-lock-warning-face on foo (but not bar)
  • font-lock-constant-face on B

I have tried to use this following code :

(defvar myregexp
  "\\(A\\) \\(?:\\(foo\\)bar \\)?\\(B\\)")

(setq mylang-font-lock-keywords `(
  (, myregex 1 font-lock-keyword-face)
  (, myregex 2 font-lock-warning-face)
  (, myregex 3 font-lock-constant-face)
))

But it does not work with the string A B (emacs report a missing capture).


Solution

  • Use subexp highlighters with laxmatch enabled to have font-lock-mode ignore missing groups in matches:

    (setq mylang-font-lock-keywords
          `((,myregexp (1 font-lock-keyword-face)
                  (2 font-lock-warning-face nil t)
                  (3 font-lock-constant-face))))
    

    The forth element of each subexp highlighter is the laxmatch argument. If t font-lock-mode ignores this highlighter if the corresponding group in the first element is not found in the match result of myregexp.

    See Search-based Fontification in the Emacs Lisp manual for more information.