Emacs Lisp: Font Lock Mode Basics
Here's the essential things you need to know about
font-lock-mode
, for writing a major mode for syntax coloring.
font-lock-mode
font-lock-mode
is a buffer-local minor mode. (that is, it can be on or off for each buffer, independent of each other.)font-lock-mode
is on by default for all buffers since ~2007.font-lock-mode
is a high-level “API” to syntax color buffer. (low level is to add Text Properties to regions of text in buffer. Font lock mode does this for you. )font-lock-mode
color text in two ways: ① “Syntactic fontification”: color comments and strings by looking up the delimiter characters for string and comments in Syntax Table, then color text between them. ② “Search based fontification”, by using regular expressions to seach text and color them. This is how keywords, function names, variable names etc, are colored.- Syntactic fontification happens first. It finds comments and strings and color them. Search-based fontification happens second. Once a text is colored, it is not changed. For example, if a text is colored as string or comment, subsequent search by regex for coloring will skip those parts.
font-lock-mode
need 2 things to do the coloring job. ① Syntax Table. ② the value of font-lock-defaults. It uses those info to go thru buffer and do syntax coloring.- Vast majority of programing language major modes do syntax color by: ① set up the proper syntax table. (in particular, the delimiter characters for string and for comment.) ② Set up proper value for font-lock-defaults.
font-lock-defaults
- font-lock-defaults is a buffer local variable. (buffer local variable means, each buffer has its own “copy”, may have different values, independent of each other.)
- font-lock-defaults variable is designed as a config for the purpose of syntax coloring. When
font-lock-mode
is on, it will use the value of font-lock-defaults to color buffer.
font-lock-defaults Value Structure
font-lock-defaults's value should be a list. If it's nil (nil is empty list), no coloring will happen, not even syntax table based one.
Emacs will automatically store each element of the list into a buffer local variable.
The first 4 elements of the list are critical. Their variable names and meaning are:
- font-lock-keywords → essentially a list of regex for coloring keywords.
- font-lock-keywords-only → whether to color comment and string using syntax table.
- font-lock-keywords-case-fold-search → whether the regex is case-sensitive.
- font-lock-syntax-table → syntax table just for coloring purposes.
Each of them must have particular form. Here's their structure:
- font-lock-keywords
- It can have many forms, but most commonly, it is list of pairs. For each pair, the first part is a regex, the second part is the face to apply.
- font-lock-keywords-only
- should be
t
or nil. nil means DO color (comments and string) by syntax table. Else, do not. By default it's nil. - font-lock-keywords-case-fold-search
- should be
t
or nil.t
means use case-insensitive regex match when searching for keywords to highlight. By default it's nil. - font-lock-syntax-table
- should be either nil or a Association List.
Each element is a cons cells of the form
(cons char-or-string string)
. These are used to set up a syntax table for syntactic fontification. If nil, buffer's syntax table is used for this purpose. (it callssyntax-table
to get the current syntax table) [see Emacs Lisp: Syntax Table]
The most important is the first element font-lock-keywords. It takes many forms. See elisp manual for detail: (info "(elisp) Search-based Fontification")
Basic Example
Here's a basic example.
Suppose you have a basic language like HTML.
You want to color any string of the form
<h1>
and
</h1>
And you want to color text between the tags. (assume there's no linebreak, and does not contain greater/less characters.)
Save the following in a file.
;; a simple major mode, my-mode (defvar my-highlights nil "first element for `font-lock-defaults'") (setq my-highlights '(("<h1>\\|</h1>" . 'font-lock-function-name-face) ("<h1>\\([^<]+?\\)</h1>" . (1 'font-lock-constant-face)))) (define-derived-mode my-mode fundamental-mode "my" "major mode for editing my language code." (setq font-lock-defaults '(my-highlights)))
Now, copy and paste the above code into a buffer, then Alt+x eval-buffer
.
Now, type following code into a buffer:
<h1>something</h1>
Now, M-x myhtml-mode
, you see words colored.

[see Emacs Lisp: How to Define Face]
[see Emacs Lisp: Syntax Table]