11

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?

Wilfred Hughes
  • 6,890
  • 2
  • 29
  • 59

1 Answers1

8

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.

Jordon Biondo
  • 12,332
  • 2
  • 41
  • 62
  • 3
    Aha, so it's expecting a variable. `(cons "foo" ''my-mode-foo-face))` also works, but I'm not sure which is idiomatic. – Wilfred Hughes Nov 15 '14 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` – Jordon Biondo Nov 15 '14 at 20:22
  • 3
    It's expecting an expression, actually, which it will evaluate. So you can also put some logic in there. – Dmitry Nov 15 '14 at 20:27