Elisp: Font Lock Mode

By Xah Lee. Date: . Last updated: .

What is Font Lock Mode

Font Lock Mode is a high-level API to syntax color text. Mostly used for coloring programing languages syntax. (low level is to add Text Properties to regions of text manually. Font lock mode does this for you.)

Font Lock Mode is a Minor Mode. (it is a buffer-local minor mode, meaning it can be on or off for each buffer, independent of each other.)

font-lock-mode is the command name to turn on off Font Lock Mode.

Font Lock Mode is on by default for all buffers since ~2007.

How to Use Font Lock Mode to Color Text

Font Lock Mode color text in two ways, in this order:

  1. Syntactic fontification → color comments and strings by looking up their delimiter characters in Syntax Table.
  2. Search based fontification → use Regular Expression to seach text and color them. This is how keywords, function names, variable names etc, are colored.

Once a text is colored, it is not changed. e.g. if a text is colored as string, subsequent search by regex for coloring skips that part.

Font Lock Mode need 2 things to do the coloring job.

Variable font-lock-defaults

font-lock-defaults Value Structure

font-lock-defaults's value is a list. If it's nil, no coloring happens, not even syntax table based one.

Emacs automatically store each element of the list into buffer local variables.

The first 4 elements of the list are critical. Their variable names are:

  1. font-lock-keywords
  2. font-lock-keywords-only
  3. font-lock-keywords-case-fold-search
  4. font-lock-syntax-table

Each of them must have particular form. Here's their meaning and 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 calls syntax-table to get the current syntax table) [see Elisp: Syntax Table]

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.

elisp font lock mode 2021-09-13
elisp font lock mode example 2021-09-13

Reference

Elisp, font lock, syntax coloring

Emacs lisp, writing a major mode. Essentials

Elisp, font face