12

If I define font lock keywords using existing faces, I can highlight the string 'foo'.

(defconst my-mode-font-lock-keywords
  (list
   (cons "foo" 'font-lock-type-face)))

(define-derived-mode my-mode fundamental-mode "My mode"
  "A demo mode."
  (set (make-local-variable 'font-lock-defaults) '(my-mode-font-lock-keywords)))

This highlights correctly:

foo highlighted correctly

However, if I define my own face:

(defface my-mode-foo-face
  '((t :inherit font-lock-preprocessor-face))
  "Face for highlighting 'foo'.")

(defconst my-mode-font-lock-keywords
  (list
   (cons "foo" 'my-mode-foo-face)))

(define-derived-mode my-mode fundamental-mode "My mode"
  "A demo mode."
  (set (make-local-variable 'font-lock-defaults) '(my-mode-font-lock-keywords)))

No highlighting is applied:

no highlighting

How can I use font-lock-defaults with a face I've defined myself?

1 Answer 1

9

Take a look at the C-hv value of font-lock-type-face the value is just the symbol font-lock-type-face. Now look at the C-hv value of my-mode-foo-face. Oh no! you can't! It's not a variable!

You need a variable to access your face. Declaring the foo-face face does not declare the foo-face variable.

Add (defvar my-mode-foo-face 'my-mode-foo-face) after the face definition and then font-lock can use your my-mode-foo-face var to access the my-mode-foo-face face. Confusing I know.


Edit: there seems to be a better solution based on what font-lock.el says:

;; Originally these variable values were face names such as `bold' etc.
;; Now we create our own faces, but we keep these variables for compatibility
;; and they give users another mechanism for changing face appearance.
;; We now allow a FACENAME in `font-lock-keywords' to be any expression that
;; returns a face.  So the easiest thing is to continue using these variables,
;; rather than sometimes evalling FACENAME and sometimes not.  sm.

;; Note that in new code, in the vast majority of cases there is no
;; need to create variables that specify face names.  Simply using
;; faces directly is enough.  Font-lock is not a template to be
;; followed in this area.

That may be Wilfred's solution of double quoting the face in the keywords.

4
  • 3
    Aha, so it's expecting a variable. (cons "foo" ''my-mode-foo-face)) also works, but I'm not sure which is idiomatic. Commented Nov 15, 2014 at 20:10
  • 1
    Hmm, my answer seems to be the antiquated solution for the problem based on what I'm reading in font-lock.el Commented Nov 15, 2014 at 20:22
  • 3
    It's expecting an expression, actually, which it will evaluate. So you can also put some logic in there.
    – Dmitry
    Commented Nov 15, 2014 at 20:27
  • Even after using this solution (thank you, by the way), I was having issues with this. Turns out that any change I made to my custom type face, I needed to restart Emacs to see it. Took me a very long time to realise that! Commented Oct 1, 2023 at 10:07

Your Answer

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

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