Elisp: Syntax Color Comments

By Xah Lee. Date: . Last updated: .

Problem

You are writing a major mode for a language. You want comment be syntax colored.

emacs doge comment coloring
coloring of comment and string.

Here's the doge text.

-*- coding: utf-8 -*-
         "Wow"

                   ▄              ▄
 such             ▌▒█           ▄▀▒▌
   simple mode    ▌▒▒█        ▄▀▒▒▒▐
                 ▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐  # comment
               ▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐
             ▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌
            ▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌
            ▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐   # colored
           ▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌
"string"   ▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌
          ▌▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐
          ▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌
          ▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐
           ▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌
           ▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐
 #  colored ▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌
              ▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀
     " too      ▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄▀   too"
                  ▒▒▒▒▒▒▒▒▒▒▀▀     Concern

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 are then automatically syntax colored, when Font Lock Mode is on.

Let's do a example.

Say our comment syntax is # to the end of line, used by Python .

Here's complete code of a major mode:

(defun my-do-syntax-table ()
  "Set local syntax table, and re-color buffer."
  (interactive)
  (let ((synTable (make-syntax-table)))
    ;; python style comment: #...
    (modify-syntax-entry ?# "<" synTable)
    (modify-syntax-entry ?\n ">" synTable)
    (set-syntax-table synTable)
    (font-lock-default-fontify-syntactically (point-min) (point-max))))

Now, copy paste the above into a buffer then Alt+x eval-buffer to evaluate the code.

Now, open a new buffer, type the following:

some "thing" # wow

Then, M-x my-do-syntax-table, you see that the string and comment are colored.

How Does Syntax Coloring Comment Works

the essential things you need to know are:

Setup Syntax Table for Programing Language Comment

Here's the appropriate syntax table setup for popular language comments syntax.

(progn
  ;; python style comment: # ...
  (set-syntax-table (make-syntax-table))
  (progn
    ;; clear the comment syntax of standard syntax table
    (modify-syntax-entry ?# ".")
    (modify-syntax-entry ?\n "."))
  (modify-syntax-entry ?# "<")
  (modify-syntax-entry ?\n ">")
  (font-lock-fontify-buffer))

(progn
  ;; C++ style comment // ...
  (set-syntax-table (make-syntax-table))
  (progn
    ;; clear the comment syntax of standard syntax table
    (modify-syntax-entry ?# ".")
    (modify-syntax-entry ?\n "."))
  (modify-syntax-entry ?\/ ". 12b")
  (modify-syntax-entry ?\n "> b")
  (font-lock-fontify-buffer))

(progn
  ;; comment style /* ... */
  ;; this is the original comment style of C
  (set-syntax-table (make-syntax-table))
  (progn
    ;; clear the comment syntax of standard syntax table
    (modify-syntax-entry ?# ".")
    (modify-syntax-entry ?\n "."))
  (modify-syntax-entry ?\/ ". 14")
  (modify-syntax-entry ?* ". 23")
  (font-lock-fontify-buffer))

(progn
  ;; comment style /* ... */ and // ...
  (set-syntax-table (make-syntax-table))
   (progn
    ;; clear the comment syntax of standard syntax table
    (modify-syntax-entry ?# ".")
    (modify-syntax-entry ?\n "."))
 (modify-syntax-entry ?\/ ". 124")
  (modify-syntax-entry ?* ". 23b")
  (modify-syntax-entry ?\n ">")
  (font-lock-fontify-buffer))

(progn
  ;; Wolfram Language style comment (* ... *)
  ;; can nest
  (set-syntax-table (make-syntax-table))
  (progn
    ;; clear the comment syntax of standard syntax table
    (modify-syntax-entry ?# ".")
    (modify-syntax-entry ?\n "."))
  (modify-syntax-entry ?\("()1n")
  (modify-syntax-entry ?\) ")(4n")
  (modify-syntax-entry ?* ". 23n")
  (font-lock-fontify-buffer))

;; HHHH------------------------------

;; todo. this does not work correctly
(progn
  ;; PowerShell comment <# ... #> and #  comment
  ;; the block comment cannot nest
  (set-syntax-table (make-syntax-table))
  (progn
    ;; clear the comment syntax of standard syntax table
    (modify-syntax-entry ?# ".")
    (modify-syntax-entry ?\n "."))

  ;; comment <# ... #> and #...
  (modify-syntax-entry ?< ". 1" xsynTable)
  (modify-syntax-entry ?> ". 4" xsynTable)
  (modify-syntax-entry ?# "< 23b" xsynTable)
  (modify-syntax-entry ?\n ">" xsynTable)

  (font-lock-fontify-buffer))
-*- coding: utf-8; mode: fundamental -*-

2024-11-30
test comment coloring.
save this in a file as
test.txt
close and open it.

then, eval emacs lisp code that sets current syntax table to see color changes for comment

# python line comment
// java line comment

/* java
block comment */

(* Wolfram language comment.
(* can be (* nested *) *) *)

<#
PowerShell
block comment
#>

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 more complex comment syntax, set up the Text Property for the key 'syntax-table .

see

Emacs Lisp, font lock, syntax coloring

Emacs Lisp, writing a major mode. Essentials