diff --git a/CHANGELOG.md b/CHANGELOG.md index eb10058..503d8c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ - [#62](https://github.com/clojure-emacs/clojure-ts-mode/issues/62): Define `list` "thing" to improve navigation in Emacs 31. - [#64]: Add defcustom `clojure-ts-auto-remap` to control remapping of `clojure-mode` buffers. +- Improve syntax highlighting: + - Highlight metadata with single keyword with `clojure-ts-keyword-face`. + - Only highlight built-ins from `clojure.core` namespace. + - Highlight named lambda functions properly. + - Fix syntax highlighting for functions and vars with metadata on the previous + line. ## 0.2.3 (2025-03-04) diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el index dba6058..30d65cc 100644 --- a/clojure-ts-mode.el +++ b/clojure-ts-mode.el @@ -384,9 +384,16 @@ with the markdown_inline grammar." marker: _ @clojure-ts-keyword-face delimiter: _ :? @default)) + ;; Highlight as built-in only if there is no namespace or namespace is + ;; `clojure.core'. :feature 'builtin :language 'clojure - `(((list_lit meta: _ :? :anchor (sym_lit (sym_name) @font-lock-keyword-face)) + `(((list_lit meta: _ :? :anchor (sym_lit !namespace name: (sym_name) @font-lock-keyword-face)) + (:match ,clojure-ts--builtin-symbol-regexp @font-lock-keyword-face)) + ((list_lit meta: _ :? :anchor + (sym_lit namespace: ((sym_ns) @ns + (:equal "clojure.core" @ns)) + name: (sym_name) @font-lock-keyword-face)) (:match ,clojure-ts--builtin-symbol-regexp @font-lock-keyword-face)) ((sym_name) @font-lock-builtin-face (:match ,clojure-ts--builtin-dynamic-var-regexp @font-lock-builtin-face))) @@ -408,12 +415,13 @@ with the markdown_inline grammar." ;; No wonder the tree-sitter-clojure grammar only touches syntax, and not semantics :feature 'definition ;; defn and defn like macros :language 'clojure - `(((list_lit :anchor meta: _ :? - :anchor (sym_lit (sym_name) @def) + `(((list_lit :anchor meta: _ :* + :anchor (sym_lit (sym_name) @font-lock-keyword-face) :anchor (sym_lit (sym_name) @font-lock-function-name-face)) (:match ,(rx-to-string `(seq bol (or + "fn" "defn" "defn-" "defmulti" @@ -423,7 +431,7 @@ with the markdown_inline grammar." "defmacro" "definline") eol)) - @def)) + @font-lock-keyword-face)) ((anon_fn_lit marker: "#" @font-lock-property-face)) ;; Methods implementation @@ -450,10 +458,10 @@ with the markdown_inline grammar." :feature 'variable ;; def, defonce :language 'clojure - `(((list_lit :anchor meta: _ :? - :anchor (sym_lit (sym_name) @def) + `(((list_lit :anchor meta: _ :* + :anchor (sym_lit (sym_name) @font-lock-keyword-face) :anchor (sym_lit (sym_name) @font-lock-variable-name-face)) - (:match ,clojure-ts--variable-definition-symbol-regexp @def))) + (:match ,clojure-ts--variable-definition-symbol-regexp @font-lock-keyword-face))) ;; Can we support declarations in the namespace form? :feature 'type @@ -479,10 +487,10 @@ with the markdown_inline grammar." :override t `((meta_lit marker: "^" @font-lock-operator-face - value: (kwd_lit (kwd_name) @font-lock-property-name-face)) + value: (kwd_lit (kwd_name) @clojure-ts-keyword-face)) (old_meta_lit marker: "#^" @font-lock-operator-face - value: (kwd_lit (kwd_name) @font-lock-property-name-face))) + value: (kwd_lit (kwd_name) @clojure-ts-keyword-face))) :feature 'tagged-literals :language 'clojure diff --git a/test/clojure-ts-mode-font-lock-test.el b/test/clojure-ts-mode-font-lock-test.el index 60b4e3e..c3cafd5 100644 --- a/test/clojure-ts-mode-font-lock-test.el +++ b/test/clojure-ts-mode-font-lock-test.el @@ -136,4 +136,30 @@ DESCRIPTION is the description of the spec." (13 16 font-lock-keyword-face) (18 20 font-lock-function-name-face) (25 31 font-lock-doc-face) - (40 46 font-lock-string-face)))) + (40 46 font-lock-string-face))) + + (when-fontifying-it "fn-with-name" + ("(fn named-lambda [x] x)" + (2 3 font-lock-keyword-face) + (5 16 font-lock-function-name-face))) + + (when-fontifying-it "single-keyword-metadata" + ("(def ^:private my-private-var true)" + (2 4 font-lock-keyword-face) + (6 6 font-lock-operator-face) + (7 14 clojure-ts-keyword-face) + (16 29 font-lock-variable-name-face) + (31 34 font-lock-constant-face))) + + (when-fontifying-it "built-ins" + ("(for [x [1 2 3]] x)" + (2 4 font-lock-keyword-face)) + + ("(clojure.core/for [x [1 2 3]] x)" + (2 13 font-lock-type-face) + (15 17 font-lock-keyword-face))) + + (when-fontifying-it "non-built-ins-with-same-name" + ("(h/for query {})" + (2 2 font-lock-type-face) + (4 6 nil)))) diff --git a/test/samples/test.clj b/test/samples/test.clj index 1ab5efa..a8a1ae9 100644 --- a/test/samples/test.clj +++ b/test/samples/test.clj @@ -13,6 +13,8 @@ (fn ^:m hello [x] @x) +(def ^:private my-var true) + (def ^Boolean x true) (clojure.core/defmacro my-mac [] @@ -20,6 +22,11 @@ ~x ~@x)) +;; Built-ins should be highlighted only for `clojure.core` namespace. +(for []) +(clojure.core/for []) +(honey.sql/for {}) + ;; the myfn sexp should have a comment face (mysfn 101 foo @@ -237,7 +244,6 @@ ([x y & more] (reduce1 max (max x y) more))) - ;; definitions with metadata only don't cause freezing (def ^String) ;; clojure-mode regression: the hanging metadata doesn't cause freezing @@ -292,6 +298,9 @@ clojure.core/map ^{:foo true} (defn b "hello" [] "world") +^{:foo bar} +(def foo "usage" "hello") + (comment (defrecord TestRecord [field] AutoCloseable