Elisp: How to Color Comment in Major Mode

By Xah Lee. Date: . Last updated: .

This page shows how to implement comment coloring for writing a major mode.

emacs doge comment coloring
coloring of comment and string. 〔doge.txt

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: Elisp: How to Write Comment Command in Major Mode)

Solution

The typical way to syntax color comment is via emacs syntax table. Two things you need to do:

  1. Set syntax table for the comment characters.
  2. 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.

  1. font-lock-mode
  2. font-lock-defaults
  3. syntax table

〔►see Elisp: Font Lock Mode Basics

〔►see Elisp: Syntax Table Tutorial

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

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.

Emacs Syntax Table Support of Comment Syntax Types
ExampleSyntax 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:

Writing Major Mode

  1. How to Write a Emacs Major Mode for Syntax Coloring
  2. Elisp: html6-mode
  3. Elisp: Font Lock Mode Basics
  4. Elisp: How to Define Face
  5. Elisp: How to Color Comment in Major Mode
  6. Elisp: How to Write Comment Command in Major Mode
  7. Elisp: How to Write Your Own Comment Command from Scratch
  8. Elisp: How to Write Keyword Completion Command
  9. Elisp: How to Create Keymap for Major Mode
  10. Elisp: Create Abbrev and Templates for Major Mode
  11. Elisp: Text Properties
  12. Elisp: Overlay Highlighting
  13. Emacs: Lookup Google, Dictionary, Documentation
  14. 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, Explained

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

Now, continue to Elisp: How to Write Comment Command in Major Mode

Liket it? Put $5 at patreon. Or Buy Xah Emacs Tutorial. Thanks.