Skip to content

Commit 68e0e13

Browse files
authored
[Fix #377] Fix font locking for def forms (#630)
1 parent 0af29f4 commit 68e0e13

File tree

4 files changed

+74
-33
lines changed

4 files changed

+74
-33
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
### Bugs fixed
1010

1111
* [#581](https://github.com/clojure-emacs/clojure-mode/issues/581): Fix font locking not working for keywords starting with a number.
12+
* [#377](https://github.com/clojure-emacs/clojure-mode/issues/377): Fix everything starting with 'def' being highlighted as a def form.
1213

1314
## 5.15.1 (2022-07-30)
1415

README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,15 @@ conservative and minimalistic.
305305
Precise font-locking requires additional data that can obtained from a running
306306
REPL (that's how CIDER's [dynamic font-locking](https://docs.cider.mx/cider/config/syntax_highlighting.html) works) or from static code analysis.
307307

308-
When it comes to definitions, `clojure-mode` employs a simple heuristic and will treat every symbol named `def`something as a built-in keyword. Still, you'll need to
309-
teach `clojure-mode` manually how to handle the docstrings of non built-in definition forms. Here's an example:
308+
When it comes to non built-in definitions, `clojure-mode` needs to be manually instructed how to handle the docstrings and highlighting. Here's an example:
310309

311310
``` emacs-lisp
312311
(put '>defn 'clojure-doc-string-elt 2)
312+
313+
(font-lock-add-keywords 'clojure-mode
314+
`((,(concat "(\\(?:" clojure--sym-regexp "/\\)?"
315+
"\\(>defn\\)\\>")
316+
1 font-lock-keyword-face)))
313317
```
314318

315319
**Note:** The `clojure-doc-string-elt` attribute is processed by the function `clojure-font-lock-syntactic-face-function`.

clojure-mode.el

+34-8
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,37 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
825825

826826
(defconst clojure-font-lock-keywords
827827
(eval-when-compile
828-
`( ;; Top-level variable definition
828+
`(;; Any def form
829+
(,(concat "(\\(?:" clojure--sym-regexp "/\\)?"
830+
"\\("
831+
(regexp-opt '("def"
832+
"defonce"
833+
"defn"
834+
"defn-"
835+
"defmacro"
836+
"definline"
837+
"defmulti"
838+
"defmethod"
839+
"defprotocol"
840+
"definterface"
841+
"defrecord"
842+
"deftype"
843+
"defstruct"
844+
;; clojure.test
845+
"deftest"
846+
"deftest-"
847+
;; clojure.logic
848+
"defne"
849+
"defnm"
850+
"defnu"
851+
"defnc"
852+
"defna"
853+
;; Third party
854+
"deftask"
855+
"defstate"))
856+
"\\)\\>")
857+
(1 font-lock-keyword-face))
858+
;; Top-level variable definition
829859
(,(concat "(\\(?:clojure.core/\\)?\\("
830860
(regexp-opt '("def" "defonce"))
831861
;; variable declarations
@@ -835,7 +865,6 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
835865
;; Possibly type or metadata
836866
"\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
837867
"\\(\\sw+\\)?")
838-
(1 font-lock-keyword-face)
839868
(2 font-lock-variable-name-face nil t))
840869
;; Type definition
841870
(,(concat "(\\(?:clojure.core/\\)?\\("
@@ -848,7 +877,6 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
848877
;; Possibly type or metadata
849878
"\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
850879
"\\(\\sw+\\)?")
851-
(1 font-lock-keyword-face)
852880
(2 font-lock-type-face nil t))
853881
;; Function definition (anything that starts with def and is not
854882
;; listed above)
@@ -861,21 +889,19 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
861889
;; Possibly type or metadata
862890
"\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
863891
(concat "\\(" clojure--sym-regexp "\\)?"))
864-
(1 font-lock-keyword-face)
865892
(2 font-lock-function-name-face nil t))
866893
;; (fn name? args ...)
867894
(,(concat "(\\(?:clojure.core/\\)?\\(fn\\)[ \t]+"
868895
;; Possibly type
869896
"\\(?:#?^\\sw+[ \t]*\\)?"
870897
;; Possibly name
871898
"\\(\\sw+\\)?" )
872-
(1 font-lock-keyword-face)
873899
(2 font-lock-function-name-face nil t))
874900
;; Special forms
875901
(,(concat
876902
"("
877903
(regexp-opt
878-
'("def" "do" "if" "let*" "var" "fn" "fn*" "loop*"
904+
'("do" "if" "let*" "var" "fn" "fn*" "loop*"
879905
"recur" "throw" "try" "catch" "finally"
880906
"set!" "new" "."
881907
"monitor-enter" "monitor-exit" "quote") t)
@@ -957,7 +983,7 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
957983
"with-redefs"
958984
"with-redefs-fn"
959985
)
960-
t)
986+
t)
961987
"\\>")
962988
1 font-lock-keyword-face)
963989
;; Macros similar to let, when, and while
@@ -1057,7 +1083,7 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
10571083
(1 'font-lock-constant-face prepend))
10581084
;; Highlight [[var]] comments
10591085
(,(rx "[[" (group-n 1 (optional "#'")
1060-
(+ (or (syntax symbol) (syntax word)))) "]]")
1086+
(+ (or (syntax symbol) (syntax word)))) "]]")
10611087
(1 'font-lock-constant-face prepend))
10621088
;; Highlight escaped characters in strings.
10631089
(clojure-font-lock-escaped-chars 0 'bold prepend)

test/clojure-mode-font-lock-test.el

+33-23
Original file line numberDiff line numberDiff line change
@@ -776,24 +776,51 @@ DESCRIPTION is the description of the spec."
776776
(6 42 clojure-keyword-face)))
777777

778778
(when-fontifying-it "should handle namespaced defs"
779-
("(_c4/defconstrainedfn bar [] nil)"
779+
("(_c4/defn bar [] nil)"
780780
(2 4 font-lock-type-face)
781781
(5 5 nil)
782-
(6 18 font-lock-keyword-face)
783-
(23 25 font-lock-function-name-face))
782+
(6 9 font-lock-keyword-face)
783+
(11 13 font-lock-function-name-face))
784784

785-
("(clo/defbar foo nil)"
785+
("(clo/defrecord foo nil)"
786786
(2 4 font-lock-type-face)
787787
(5 5 nil)
788-
(6 11 font-lock-keyword-face)
789-
(13 15 font-lock-function-name-face))
788+
(6 14 font-lock-keyword-face)
789+
(16 18 font-lock-function-name-face))
790790

791791
("(s/def ::keyword)"
792792
(2 2 font-lock-type-face)
793793
(3 3 nil)
794794
(4 6 font-lock-keyword-face)
795795
(8 16 clojure-keyword-face)))
796796

797+
(when-fontifying-it "should handle any known def form"
798+
("(def a 1)" (2 4 font-lock-keyword-face))
799+
("(defonce a 1)" (2 8 font-lock-keyword-face))
800+
("(defn a [b])" (2 5 font-lock-keyword-face))
801+
("(defmacro a [b])" (2 9 font-lock-keyword-face))
802+
("(definline a [b])" (2 10 font-lock-keyword-face))
803+
("(defmulti a identity)" (2 9 font-lock-keyword-face))
804+
("(defmethod a :foo [b] (println \"bar\"))" (2 10 font-lock-keyword-face))
805+
("(defprotocol a (b [this] \"that\"))" (2 12 font-lock-keyword-face))
806+
("(definterface a (b [c]))" (2 13 font-lock-keyword-face))
807+
("(defrecord a [b c])" (2 10 font-lock-keyword-face))
808+
("(deftype a [b c])" (2 8 font-lock-keyword-face))
809+
("(defstruct a :b :c)" (2 10 font-lock-keyword-face))
810+
("(deftest a (is (= 1 1)))" (2 8 font-lock-keyword-face))
811+
("(defne [x y])" (2 6 font-lock-keyword-face))
812+
("(defnm a b)" (2 6 font-lock-keyword-face))
813+
("(defnu)" (2 6 font-lock-keyword-face))
814+
("(defnc [a])" (2 6 font-lock-keyword-face))
815+
("(defna)" (2 6 font-lock-keyword-face))
816+
("(deftask a)" (2 8 font-lock-keyword-face))
817+
("(defstate a :start \"b\" :stop \"c\")" (2 9 font-lock-keyword-face)))
818+
819+
(when-fontifying-it "should ignore unknown def forms"
820+
("(defbugproducer me)" (2 15 nil))
821+
("(default-user-settings {:a 1})" (2 24 nil))
822+
("(s/deftartar :foo)" (4 10 nil)))
823+
797824
(when-fontifying-it "should handle variables defined with def"
798825
("(def foo 10)"
799826
(2 4 font-lock-keyword-face)
@@ -845,23 +872,6 @@ DESCRIPTION is the description of the spec."
845872
(2 5 font-lock-keyword-face)
846873
(7 9 font-lock-function-name-face)))
847874

848-
(when-fontifying-it "should handle a custom def with special chars 1"
849-
("(defn* foo [x] x)"
850-
(2 6 font-lock-keyword-face)
851-
(8 10 font-lock-function-name-face)))
852-
853-
(when-fontifying-it "should handle a custom def with special chars 2"
854-
("(defsomething! foo [x] x)"
855-
(2 14 font-lock-keyword-face)
856-
(16 18 font-lock-function-name-face)))
857-
858-
(when-fontifying-it "should handle a custom def with special chars 3"
859-
("(def-something foo [x] x)"
860-
(2 14 font-lock-keyword-face))
861-
862-
("(def-something foo [x] x)"
863-
(16 18 font-lock-function-name-face)))
864-
865875
(when-fontifying-it "should handle fn"
866876
;; try to byte-recompile the clojure-mode.el when the face of 'fn' is 't'
867877
("(fn foo [x] x)"

0 commit comments

Comments
 (0)