Wilfred Hughes
Wilfred Hughes

Reputation: 31141

How do I ensure the correct precedence in Emacs highlighting keywords?

I'm trying to write a simple major mode for a lisp dialect. Here's my mode:

(defconst example-font-lock-keywords
  (list
   `(";.*" . font-lock-comment-face)
   `(,(regexp-opt '("function" "macro") 'symbols) . font-lock-builtin-face)
   `("\"[^\"]+?\"" . font-lock-string-face))
  "Highlighting for Example mode.")

(defvar example-mode-syntax-table
  (make-syntax-table))

(define-derived-mode example-mode lisp-mode "Example"
  "Major mode for editing Example lisp code."
  :syntax-table example-mode-syntax-table
  (set (make-local-variable 'font-lock-defaults) '(example-font-lock-keywords)))

Here's my sample program:

; Highlighting tests.
; This is a comment despite "quotes"

(function foo () "bar")

Here's the result I'm seeing:

emacs screenshot

What am I doing wrong? Why does the string regexp 'win' against the comment regexp?

Upvotes: 2

Views: 505

Answers (2)

Lindydancer
Lindydancer

Reputation: 26094

Emacs highlights a buffer in two phases. The first is the syntactic phase, which is based on information found in the syntax table, which typically highlights strings and comments. The second is the keyword phase.

In your case, the default syntax table sets up double quotes to mean string. The effect is that before your keywords are executed, the strings are already highlighted. By default, a keyword is only applied when there is no highlighting in the matched content, which is the reason why your comment keyword only works on lines without strings. (See the OVERRIDE flag in the help text of font-lock-keywords for details on overriding.)

The best solution for you is to update the syntax table so that ; means "comment start", and then drop the comment and string rules from your set of keywords.

Upvotes: 3

Drew
Drew

Reputation: 30701

Try ("\"[^\"]+?\"" 0 font-lock-string-face keep t).

Or reverse the order of the two entries (for font-lock-comment-face and font-lock-string-face).

See the Elisp manual, node Search-based Fontification -- look for OVERRIDE for an explanation of keep.

Upvotes: 1

Related Questions