From f0eee5afe77eb2c18a910547ca93c7906cd43839 Mon Sep 17 00:00:00 2001
From: Marconi Rivello <marconi.rivello@gmail.com>
Date: Mon, 22 Mar 2021 16:40:59 -0300
Subject: [PATCH] Fix for character literal font-lock (#588)

When inside a vector or before white space, some escaped characters,
like comma, square and curly brackets, weren't being formatted.

* Added tests.
* Added examples in test.clj for visual inspection.
---
 CHANGELOG.md                        |  1 +
 clojure-mode.el                     | 20 ++++++++++----------
 test.clj                            |  2 +-
 test/clojure-mode-font-lock-test.el | 16 ++++++++++++++++
 4 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f7e9c9a0..8e8c2fdc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
 * [#574](https://github.com/clojure-emacs/clojure-mode/issues/574): Remove `clojure-view-grimoire` command.
 * Stop `clojure-sort-ns` from calling `redisplay`.
 * [#584](https://github.com/clojure-emacs/clojure-mode/issues/584): Align to recent `pcase` changes on Emacs master.
+* [#588](https://github.com/clojure-emacs/clojure-mode/pull/588): Fix font-lock for character literals.
 
 ## 5.12.0 (2020-08-13)
 
diff --git a/clojure-mode.el b/clojure-mode.el
index 6579d394..db7d214a 100644
--- a/clojure-mode.el
+++ b/clojure-mode.el
@@ -801,8 +801,6 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
                 "\\(\\sw+\\)?" )
        (1 font-lock-keyword-face)
        (2 font-lock-function-name-face nil t))
-      ;; lambda arguments - %, %&, %1, %2, etc
-      ("\\<%[&1-9]?" (0 font-lock-variable-name-face))
       ;; Special forms
       (,(concat
          "("
@@ -862,14 +860,16 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
          "\\>")
        0 font-lock-constant-face)
       ;; Character literals - \1, \a, \newline, \u0000
-      (,(rx "\\" (or any
-                    "newline" "space" "tab" "formfeed" "backspace"
-                    "return"
-                    (: "u" (= 4 (char "0-9a-fA-F")))
-                    (: "o" (repeat 1 3 (char "0-7"))))
-            word-boundary)
-       0 'clojure-character-face)
-
+      (,(rx (group "\\" (or any
+                            "newline" "space" "tab" "formfeed" "backspace"
+                            "return"
+                            (: "u" (= 4 (char "0-9a-fA-F")))
+                            (: "o" (repeat 1 3 (char "0-7")))))
+            (or (not word) word-boundary))
+       1 'clojure-character-face)
+      ;; lambda arguments - %, %&, %1, %2, etc
+      ;; must come after character literals for \% to be handled properly
+      ("\\<%[&1-9]?" (0 font-lock-variable-name-face))
       ;; namespace definitions: (ns foo.bar)
       (,(concat "(\\<ns\\>[ \r\n\t]*"
                 ;; Possibly metadata, shorthand and/or longhand
diff --git a/test.clj b/test.clj
index 7652b7ab..147171a1 100644
--- a/test.clj
+++ b/test.clj
@@ -51,7 +51,7 @@
     minnow))
 
 ;; character literals
-[\a \newline \u0032 \/ \+ \,, \;]
+[\a \newline \u0032 \/ \+ \,, \; \( \% \)]
 
 ;; TODO change font-face for sexps starting with @,#
 (comment ;; examples
diff --git a/test/clojure-mode-font-lock-test.el b/test/clojure-mode-font-lock-test.el
index c6261227..5e2b63a0 100644
--- a/test/clojure-mode-font-lock-test.el
+++ b/test/clojure-mode-font-lock-test.el
@@ -942,6 +942,22 @@ DESCRIPTION is the description of the spec."
     ("\\ク"
      (1 2 clojure-character-face)))
 
+  (when-fontifying-it "should handle characters not by themselves"
+    ("[\\,,]"
+     (1 1 nil)
+     (2 3 clojure-character-face)
+     (4 5 nil))
+
+    ("[\\[]"
+     (1 1 nil)
+     (2 3 clojure-character-face)
+     (4 4 nil)))
+
+  (when-fontifying-it "should handle % character literal"
+    ("#(str \\% %)"
+     (7 8 clojure-character-face)
+     (10 10 font-lock-variable-name-face)))
+
   (when-fontifying-it "should handle referred vars"
     ("foo/var"
      (1 3 font-lock-type-face))