Emacs Lisp: Syntax Color Comment in Major Mode
This page shows how to implement comment coloring for writing a major mode.

Here's the doge text.
-*- coding: utf-8 -*- "Wow" ▄ ▄ such ▌▒█ ▄▀▒▌ simple mode ▌▒▒█ ▄▀▒▒▒▐ ▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐ # comment ▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐ ▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌ ▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌ ▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐ # colored ▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌ "string" ▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌ ▌▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐ ▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌ ▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐ ▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌ ▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐ # colored ▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌ ▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀ " too ▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄▀ too" ▒▒▒▒▒▒▒▒▒▒▀▀ Concern
Problem
You are writing a major mode for a language. You want comment be syntax colored.
(For how to write a command to comment/uncomment, see: Emacs Lisp: How to Write Comment/Uncomment Command for a Major Mode)
Solution
The typical way to syntax color comment is via emacs syntax table. Two things you need to do:
- Set syntax table for the comment characters.
- Set font-lock-defaults to non-nil.
Comment AND string will then automatically be syntax colored, when font-lock-mode
is on. (it is on by default)
Let's do a example.
Say our comment syntax is # to the end of line, used by Ruby, Python, Perl, PHP, Bash.
Here's complete code of a major mode:
;; sample mode that does coloring of python style commment syntax (defvar xpy-mode-syntax-table nil "Syntax table for `xpy-mode'.") (setq xpy-mode-syntax-table (let ( (synTable (make-syntax-table))) ;; python style comment: “# …” (modify-syntax-entry ?# "<" synTable) (modify-syntax-entry ?\n ">" synTable) synTable)) (define-derived-mode xpy-mode prog-mode "xpy" "xpy-mode is a major mode for editing language xpy." (setq font-lock-defaults (list nil nil)) (set-syntax-table xpy-mode-syntax-table) ;; actually no need, because our syntax table name is “xpy-mode” + “-syntax-table”, so define-derived-mode will find it and set it )
Now, copy paste the above into a buffer then call eval-buffer
to evaluate the code.
Now, open a new buffer, type the following:
some "thing" # wow
Then, M-x xpy-mode
, you see that the string and comment are colored.
How Does Syntax Coloring Works
3 essential things you need to know.
font-lock-mode
- font-lock-defaults
- syntax table
[see Emacs Lisp: Font Lock Mode Basics]
[see Emacs Lisp: Syntax Table]
Here's the appropriate syntax table setup for popular languages.
C++ Style Comments
Comment style of the form //…
(defvar xcpp-mode-syntax-table nil "Syntax table for `xcpp-mode'.") (setq xcpp-mode-syntax-table (let ( (synTable (make-syntax-table))) ;; C++ style comment “// …” (modify-syntax-entry ?\/ ". 12b" synTable) (modify-syntax-entry ?\n "> b" synTable) synTable)) (define-derived-mode xcpp-mode prog-mode "xcpp" "xcpp-mode is a major mode for editing language xcpp." (setq font-lock-defaults (list nil)))
Java Style Comments
Comment style of the form /*…*/
(defvar xjv-mode-syntax-table nil "Syntax table for `xjv-mode'.") (setq xjv-mode-syntax-table (let ( (synTable (make-syntax-table))) ;; comment style “/* … */” (modify-syntax-entry ?\/ ". 14" synTable) (modify-syntax-entry ?* ". 23" synTable) synTable)) (define-derived-mode xjv-mode prog-mode "xjv" "xjv-mode is a major mode for editing language xjv." (setq font-lock-defaults (list nil)))
Haskell Style Comments
Here's example for comment style of the form
(*…*)
(Wolfram Language, Pascal, OCaml, Applescript){-…-}
(Haskell)
etc.
(defvar xwl-mode-syntax-table nil "Syntax table for `xwl-mode'.") (setq xwl-mode-syntax-table (let ((synTable (make-syntax-table))) ;; Wolfram Language style comment “(* … *)” (modify-syntax-entry ?\( ". 1" synTable) (modify-syntax-entry ?\) ". 4" synTable) (modify-syntax-entry ?* ". 23" synTable) synTable)) (define-derived-mode xwl-mode prog-mode "xwl" "xwl-mode is a major mode for editing language xwl." (setq font-lock-defaults (list nil)))
Syntax Table Supports Limited Comment Syntax
Emacs's syntax table only supports comment syntaxes that are used in mainstream languages.
Example | Syntax Type |
---|---|
# …\n (Python, Perl, PHP, Bash, shells); …\n (lisp)' …\n (Visual Basic) | Start with a char to newline char. |
// … \n (C, C++, C#, Java, JavaScript, PHP) | Start with 2 identical chars to newline char. |
(* … *) (Mathematica, Pascal, OCaml, Applescript){- … -} (Haskell) | A matching pair chars with another char. |
/* … */ (C, C++, C#, Java, JavaScript) | Two chars used in a ad hoc way as matching pair. |
If your language's comment syntax is not one of the above, then emacs syntax table is not able to capture it.
To handle non-mainstream comment syntax, you have 2 ways:
- Use Search-based Fontification of
font-lock-mode
to color comment. See Font Lock Mode (ELISP Manual) - Write your own parser, then use text properties to color them. [see Emacs Lisp: Text Properties]
Now, continue to Emacs Lisp: How to Write Comment/Uncomment Command for a Major Mode