Elisp: How to Define Face

By Xah Lee. Date: . Last updated: .

Here's a quick tutorial on how to define face in your own major mode.

What's Face

A face is a collection of graphical attributes for displaying text: font, foreground color, background color, optional underlining, etc. Faces control how Emacs displays text in buffers, as well as other parts of the frame such as the mode line.

[(info "(elisp) Faces")]

It is the “face” that makes syntax coloring in emacs possible.

In emacs major mode, typically you use higher-level font-lock-mode system to color your language words. Basically, just assign a list to the variable font-lock-defaults.

For example:

;; a simple major mode, mymath-mode

(setq mymath-highlights
      '(("Sin\\|Cos\\|Sum" . font-lock-function-name-face)
        ("Pi\\|Infinity" . font-lock-constant-face)))

(define-derived-mode mymath-mode prog-mode "mymath"
  "major mode for editing mymath language code."
  (setq font-lock-defaults '(mymath-highlights)))

[see How to Write a Emacs Major Mode for Syntax Coloring]

The font-lock-function-name-face and font-lock-constant-face are predefined faces.

Predefined Faces

To list all loaded faces, Alt+x list-faces-display.

emacs list faces display 2016 12 29
emacs Alt+x list-faces-display

list-faces-display lists all loaded faces, including those in packages you installed.

The following are faces predefined by font-lock-mode.

(These are both face and variable.)

If you are creating a programing language mode, use these face as much as possible, because that will create consistent style of coloring for programing languages in emacs.

Here's pre-defined faces in emacs.

Again, you should use pre-defined faces as much as possible. This makes highlight more consistent.

Define Face

To define a face, use defface.

;; examples of defining faces

(defface my-lang-phi-word
  '((t :foreground "black"
       :background "aquamarine"
       :weight bold
       :underline t
  "Face for function parameters."
  :group 'my-lang-mode )

(defface my-lang-gamma-word
  '((t :foreground "red"
       :background "#f5f5f5"
  "Face for global variables."
  :group 'my-lang-mode )

You can use the above code as a template to define your faces.

Alt+x list-colors-display to list named colors and their hexadecimal values.

Emacs's face system supports terminal emulators that has limited colors. For example, you can define a face such that when user is in a terminal that only has 8 colors, the face will use a available color and still sensible.

For example, here’s the definition of the standard face highlight:

(defface highlight
  '((((class color) (min-colors 88) (background light))
     :background "darkseagreen2")
    (((class color) (min-colors 88) (background dark))
     :background "darkolivegreen")
    (((class color) (min-colors 16) (background light))
     :background "darkseagreen2")
    (((class color) (min-colors 16) (background dark))
     :background "darkolivegreen")
    (((class color) (min-colors 8))
     :background "green" :foreground "black")
    (t :inverse-video t))
  "Basic face for highlighting."
  :group 'basic-faces)

(info "(elisp) Defining Faces")

Note: elisp manual says face name should not end in “-face” and reason being “redundant”.

Face Attributes (styles)

You can specify font, size, weight, text color, background color, underline, overline, border, slant (italic), etc. To see complete list of attributes, see: (info "(elisp) Face Attributes")

Redefine Face

When you are working on major mode, often you need to experiment on which color/face is best.

defface won't set the face when a face name already has a face spec. (that is, when you change a face's spec and re-eval the buffer, your new spec has no effect.)

Use face-spec-set to force set a face spec.

(defface is like defvar, and face-spec-set is like setq.)

(defface my-identifier-x
  '((t :foreground "red"
      :weight bold
  "face for user defined variables."
  :group 'my-mode )

 '((t :foreground "blue"
      :weight bold

Face Name vs Face Variable

Note: A face name is not a variable. defface does not create a new variable. That is, defface does not set the symbol's value cell. (boundp 'face_name) returns nil.

A named face (such as those created by defface) is specified by setting the face-defface-spec property name of the symbol's property list. (info "(elisp) Standard Properties")

You could, use defvar to make a face_name symbol also a variable, but that is not necessary.

Those faces predefined from font-lock-mode, such as font-lock-function-name-face, are variables, and also a face name.

You can check if a symbol is a face by facep.

You can check if a symbol is a variable by boundp.

;; example of user defined face

(defface my-great-face
  '((t :foreground "red"))
  "my face"

;; check if a symbol is a variable. that is, value cell is not void
(boundp 'my-great-face) ; nil

;; check if a symbol is a face
(facep 'my-great-face) ; non-nil

;; get the value of 'face-defface-spec from symbol's plist
(get 'my-great-face 'face-defface-spec ) ; ((t :foreground "red" :weight bold))

;; now make it a variable. (you shouldn't do this)
(defvar my-great-face nil "my face too")

(boundp 'my-great-face) ; t

See also: Elisp: Lisp Symbol

Writing Major Mode

  1. How to Write a Emacs Major Mode for Syntax Coloring
  2. Elisp: Font Lock Mode Basics
  3. Elisp: How to Define Face
  4. Elisp: How to Color Comment in Major Mode
  5. Elisp: How to Write Comment Command in Major Mode
  6. Elisp: How to Write Your Own Comment Command from Scratch
  7. Elisp: How to Write Keyword Completion Command
  8. Elisp: How to Create Keymap for Major Mode
  9. Elisp: Abbrev, Template, for Major Mode
  10. Elisp: Text Properties
  11. Elisp: Overlay Highlighting
  12. Emacs: Lookup Google, Dictionary, Documentation
  13. Elisp: Syntax Table Tutorial

  1. Elisp: How to Name Your Major Mode
  2. Elisp: What's “feature”?
  3. Elisp: require, load, load-file, autoload, feature

Syntax Table

  1. Elisp: Syntax Table Tutorial
  2. Elisp: How to Find Syntax of a Character?
  3. Elisp: How to Modify Syntax Table Temporarily
  4. Elisp: How to Determine If Cursor is Inside String or Comment
  5. Elisp: Regex Patterns and Syntax Table
  6. Elisp: Find Matching Bracket Character
Patreon me $5 patreon

Or Buy Xah Emacs Tutorial

Or buy a nice keyboard: Best Keyboard for Emacs

If you have a question, put $5 at patreon and message me.