AddKeywords

Here’s the normal way of adding new keywords to a mode. Let us start with the simplest example:

(font-lock-add-keywords 'emacs-lisp-mode
  '(("foo" . font-lock-keyword-face)))

It makes “foo” a keyword in EmacsLisp mode.

More Examples

Here is a simple example from the documentation of font-lock-add-keywords:

(font-lock-add-keywords 'c-mode
  '(("\\<\\(FIXME\\):" 1 font-lock-warning-face prepend)
    ("\\<\\(and\\|or\\|not\\)\\>" . font-lock-keyword-face)))

It adds two fontification patterns for C mode, to fontify `FIXME:’ words, even in comments, and to fontify ‘and’, ‘or’ and ‘not’ words as keywords.

Here’s an example for plain HtmlMode:

(defvar html-mode-keywords
  '(("<\\(/?\\(em\\|p\\|q\\|h[r1-6]\\|pre\\|code\\|b\\(lockquote\\|r\\)?\\|i\\|ol\\|ul\\|li\\|center\\)\\)>" 1 font-lock-type-face)
    ("title=\\|re[lv]=\\|h\\(ref=\\|ttp-equiv=\\)\\|content=\\|name=" . font-lock-variable-name-face)
    ("<\\(a\\)" 1 font-lock-function-name-face)
    ("\\(/a\\)>" 1 font-lock-function-name-face)
    ("\t" . 'show-paren-mismatch-face)))

(font-lock-add-keywords 'html-mode html-mode-keywords)

Explanation

Every Element has one of the following forms:

(REGEXP . FACE)
Highlight REGEXP with FACE
(REGEXP N FACE)
Highlight group N in REGEXP with FACE
(REGEXP (N1 FACE1) (N2 FACE2) (N3 FACE3) …)
Highlight group Ni in REGEXP with FACEi

Add keywords to all major modes

Here’s another example. Here, we don’t just call font-lock-add-keywords – we loop over a list of major modes and add the keywords to all the modes in the list.

;; agressive whitespace marking.
(defface extra-whitespace-face
  '((t (:background "pale green")))
  "Used in text-mode and friends for exactly one space after a period.")

(mapcar (lambda (mode)
	  (font-lock-add-keywords
	   mode
	   '(("FIXME" 0 'show-paren-mismatch-face)
	     ("\\.\\( \\)\\b" 1 'extra-whitespace-face))))
	'(text-mode latex-mode html-mode emacs-lisp-mode
	  texinfo-mode))

The second REGEXP highlights all single spaces after a point. (I want there to be two spaces unless we’re talking about abbreviations.)

More info

Manual: https://www.gnu.org/software/emacs/manual/html_node/elisp/Font-Lock-Mode.html

For even more information, see FontLockKeywords.

For other ways to highlight keywords, take a look at the different packages in: Highlight Temporarily

Adding a Bunch of Scheme Keywords

Here’s how I add highlighting and indent rules for Scheme constructs.

 (defun scheme-add-keywords (face-name keyword-rules)
   (let* ((keyword-list (mapcar #'(lambda (x)
                                    (symbol-name (cdr x)))
                                keyword-rules))
          (keyword-regexp (concat "(\\("
                                  (regexp-opt keyword-list)
                                  "\\)[ \n]")))
     (font-lock-add-keywords 'scheme-mode
                             `((,keyword-regexp 1 ',face-name))))
   (mapc #'(lambda (x)
             (put (cdr x)
                  'scheme-indent-function
                  (car x)))
         keyword-rules))
 
 (scheme-add-keywords
  'font-lock-keyword-face
  '((1 . when)
    (1 . unless)
    (2 . let1)
    (1 . error)
    ))

The numbers tell how many arguments the construct should take on the same line. For example, (1 . when) causes the following indentation:

 (when (test)
   body-1
   body-2),

while (0 . when) causes this:

 (when (test)
       body-1
       body-2).

The former is usually preferred.

Feel free to generalize this (to all Lisps?).

Printf Format Specifier

A highlighting printf format specifier like vim…

(defvar font-lock-format-specifier-face		
  'font-lock-format-specifier-face
  "Face name to use for format specifiers.")

(defface font-lock-format-specifier-face
  '((t (:foreground "OrangeRed1")))
  "Font Lock mode face used to highlight format specifiers."
  :group 'font-lock-faces)

(add-hook 'c-mode-common-hook
	  (lambda ()
	    (font-lock-add-keywords nil
				    '(("[^%]\\(%\\([[:digit:]]+\\$\\)?[-+' #0*]*\\([[:digit:]]*\\|\\*\\|\\*[[:digit:]]+\\$\\)\\(\\.\\([[:digit:]]*\\|\\*\\|\\*[[:digit:]]+\\$\\)\\)?\\([hlLjzt]\\|ll\\|hh\\)?\\([aAbdiuoxXDOUfFeEgGcCsSpn]\\|\\[\\^?.[^]]*\\]\\)\\)"
				       1 font-lock-format-specifier-face t)
				      ("\\(%%\\)" 
				       1 font-lock-format-specifier-face t)) )))

Note that this will highlight printf specifiers outside of strings, so “a=num%amount” will have the “%a” highlighted.

C typedefs

There exists a module ctypes.el, written by AndersLindgren, that will spider through your open buffers looking for typedefs and dynamically cause them to be interpreted as type names for the purposes of syntax coloring. It works with C and “maybe” C++ sources.

See Lisp:ctypes.el.

XEmacs

If you write a ~/.emacs for both Emacs and XEmacs, you might be using ‘font-lock-add-keywords’ a lot. This function is in XEmacs 21.5, but not earlier versions. If you are are using 21.4 or older, use the following workaround. See ComparativeEmacsology for similar problems.

(unless (fboundp 'font-lock-add-keywords)
  (defalias 'font-lock-add-keywords 'ignore))

See AddBufferKeywords for an alternative but Emacs-agnostic approach.


CategoryFaces