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: (1) “Syntactic fontification”: color comments and strings by looking up the delimiter characters for string and comments in Syntax Table, then color text between them. (2) “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. (1) Syntax Table. (2) 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: (1) set up the proper syntax table. (in particular, the delimiter characters for string and for comment.) (2) Set up proper value for font-lock-defaults.
font-lock-defaults
- font-lock-defaults is a Buffer Local Variable.
- 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, 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 . If t, the coloring by Syntax Table is not done (they are simply not colored). 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: Search-based Fontification (ELISP Manual)
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 is 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]