Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* [#709](https://github.com/clojure-emacs/clojure-mode/pull/709): Fix `clojure-get-indent-spec` and `put-clojure-indent` converting legacy indent specs, like those of `letfn`, `reify` or `extend-protocol`, to the wrong modern rules.
* [#709](https://github.com/clojure-emacs/clojure-mode/pull/709): Fix indenting with a modern indent spec that has an `:inner` rule with a position but no `:block` rule, like `((:inner 1 0))`, which signaled an error.
* [#711](https://github.com/clojure-emacs/clojure-mode/pull/711): Fix the indentation of `letfn` functions, and of other forms an `:inner` rule with an index applies to, when a `#_` form comes before them, as the discarded form and its `#_` counted as two arguments.
* [#707](https://github.com/clojure-emacs/clojure-mode/issues/707): Highlight `[[var]]` and `` `code` `` only in strings and comments, so Datalog relation bindings like `[[?x]]` and destructuring like `(fn [[x]] x)` aren't colored as constants in code.

## 5.23.0 (2026-03-25)

Expand Down
27 changes: 23 additions & 4 deletions clojure-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -1226,12 +1226,18 @@ whether the paren is a direct child of a letfn binding vector."
'clojure-discard-face font-lock-comment-face)
t)
;; Highlight `code` marks, just like `elisp'.
(,(rx "`" (group-n 1 (optional "#'")
(+ (or (syntax symbol) (syntax word)))) "`")
(,(lambda (bound)
(clojure--search-in-string-or-comment
(rx "`" (group-n 1 (optional "#'")
(+ (or (syntax symbol) (syntax word)))) "`")
bound))
(1 'font-lock-constant-face prepend))
;; Highlight [[var]] comments
(,(rx "[[" (group-n 1 (optional "#'")
(+ (or (syntax symbol) (syntax word)))) "]]")
(,(lambda (bound)
(clojure--search-in-string-or-comment
(rx "[[" (group-n 1 (optional "#'")
(+ (or (syntax symbol) (syntax word)))) "]]")
bound))
(1 'font-lock-constant-face prepend))
;; Highlight escaped characters in strings.
(clojure-font-lock-escaped-chars 0 'bold prepend)
Expand Down Expand Up @@ -1374,6 +1380,19 @@ preceded by a #."
;; When regexp is nil, match any string (both #"..." and "...").
string-beg))))))

(defun clojure--search-in-string-or-comment (regexp bound)
"Search forward for REGEXP in a string or a comment, up to BOUND.
In code, the same text can be something else entirely, like the
[[?x]] relation binding of a Datalog query."
(let ((found nil))
(while (and (not found)
(re-search-forward regexp bound t))
(setq found (save-match-data
(save-excursion
(ppss-comment-or-string-start
(syntax-ppss (match-beginning 0)))))))
found))

(defun clojure-font-lock-escaped-chars (bound)
"Highlight \\escaped chars in strings.
BOUND denotes a buffer position to limit the search."
Expand Down
10 changes: 10 additions & 0 deletions test/clojure-mode-font-lock-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,16 @@ DESCRIPTION is the description of the spec."
(4 11 (font-lock-constant-face font-lock-comment-face))
(12 13 font-lock-comment-face)))

(when-fontifying-it "should leave double brackets and backticks alone in code"
("(fn [[x]] x)"
(7 7 nil))

("[(q '[:find (min ?d)] $) [[?d]]]"
(28 29 nil))

("(list `a`b)"
(8 8 nil)))

(when-fontifying-it "should fontify let, when, and while type forms"
("(when-alist [x 1]\n ())"
("when-alist" font-lock-keyword-face))
Expand Down
Loading