Elisp: How to Define Face
Here's a quick tutorial on how to define face in your own major mode.
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.
;; 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.
To list all loaded faces, Alt+x
list-faces-display lists all loaded faces, including those in packages you installed.
The following are faces predefined by
(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.
To define a face, use
;; 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.
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
(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")
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.)
face-spec-set to force set a face spec.
defface is like
face-spec-set is like
(defface my-identifier-x '((t :foreground "red" :weight bold )) "face for user defined variables." :group 'my-mode ) (face-spec-set 'my-identifier-x '((t :foreground "blue" :weight bold )) 'face-defface-spec )
Face Name vs Face Variable
Note: A face name is not a variable.
defface does not create a new variable.
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
You can check if a symbol is a variable by
;; 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
Elisp, Writing Major Mode
- Syntax Coloring
- Font Lock Mode
- Define Face
- Color Comment
- Comment Command
- Your Own Comment Command
- Keyword Completion Command
- Create Keymap
- Text Properties
- Overlay Highlighting
- Lookup Doc
- Syntax Table