2

I'm trying to learn about font locking in my own custom major modes. I can get things working fine for the most part, keywords highlighted, regexp-opt matching strings, using capture groups within a regexp to highlight just the capture group, etc.

But I've noticed that some of the faces that I have tried (such as dired-directory) do not work in font lock expressions, even though other faces such as font-lock-keyword-face work fine in the same slot.

Reading the manual says that face variables should be faces that have a value property that evaluates to the face name. Sure enough, when I eval font-lock-keyword-face, the value is the same as the face name. But when I eval dired-directory face, its value is nil.

So it looks like the value nil is the proximal cause of the problem, and the answer to my question (kind of). But it's not really a good answer.

(1) Why doesn't the dired-directory face that I see listed with list-faces-display have a value the same as the face name?

(2) How can any mode use the face, if the font lock implementation requires that the face name symbol evaluates to the face name, when dired-directory face does not?

Here is a link in SX that touches on the same subject, but it mentions that the solution might be obsolete.

Update

Here is my code line that motivated the problem.

 ( ,(regexp-opt ct-mode-nset-keywords ) . font-lock-keyword-face)

(1) Using font-lock-keyword-face (with no quote) works. (2) Using dired-directory (with no quote) fails. (3) Thanks to @theldoria, using 'dired-directory (with quote) works.

Here is what the manual says:

22.6.7 Faces for Font Lock

Font Lock mode can highlight using any face, but Emacs defines several faces specifically for Font Lock to use to highlight text. These Font Lock faces are listed below. They can also be used by major modes for syntactic highlighting outside of Font Lock mode (see Major Mode Conventions).

Each of these symbols is both a face name, and a variable whose default value is the symbol itself. Thus, the default value of font-lock-comment-face is font-lock-comment-face.

Thank you to everyone who responded -- I have a working syntax to use going forward. And sorry for the confusion using dired-directory as my example - it is both a face and a separate variable holding a directory (or nil). It would have been better for me to use dired-flagged or some other face from list-faces-display, which trigger a void variable error instead of nil.

But now I'm wondering if the face-symbol-with-variable-value model is somehow old or obsolete, even if it is in the manual. Font lock apparently requires that variable value one way or another (eg with a 'quoted-face-name), but other faces in the list-faces-display do not have that value property (eg. dired-flagged, avy-lead-face, etc).

  • Faces are not variables, they're some properties stored in the symbol plist of the face symbol in question. Personally, I believe it to be a mistake to have permitted variables inside font-lock-keywords as it's just confusing people when they're using a face name that is no variable and get the syntax wrong... – wasamasa Aug 14 '16 at 16:17
  • You can quote the faces, e.g. (font-lock-add-keywords nil '(("^[ \t]*\\([^ \t\n]+\\)[ \t]+\\([[:alpha:]][^ \t\n]*\\)" (1 'font-lock-keyword-face) (2 'dired-directory)))). – theldoria Aug 14 '16 at 19:44
3

Variable dired-directory does not have face dired-directory as its value. Instead, it has a directory as its value (as you can see by C-h v dired-directory).

In general, faces are not associated with variables; that is, there is no variable whose value is a given face. And it is generally recommended not to create and use a face-valued variable, just to be able to use its face. Use the face directly, instead.

So for example, if you want to refer to face dired-directory then simply refer to that symbol. In most contexts this means passing the quoted symbol, so that evaluation returns the symbol: 'dired-directory.

Just remember the general rule that you should never (or nearly never) need to refer to a face-valued variable, just in order to refer to its (face) value.

In some older parts of Emacs, including font lock, there are still some face-valued variables, and this can confuse things.

Another, more legitimate use of a face-valued variable is a user option, whose value is intended to be changed (customized) from one face to another. In this case, the option name typically is not, and generally should not be, the name of any given face.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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