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 @@ -49,6 +49,7 @@
- [#164](https://github.com/clojure-emacs/clojure-ts-mode/pull/164): Support `setopt-local` for `clojure-ts-indent-style`, `clojure-ts-extra-def-forms` and `clojure-ts-comment-macro-font-lock-body`, which Emacs 31 refused to set locally and Emacs 32 warned about in `.dir-locals.el`.
- [#168](https://github.com/clojure-emacs/clojure-ts-mode/pull/168): Indent docstrings like `clojure-mode`, moving the lines indented less than `clojure-ts-docstring-fill-prefix-width` to that column and keeping deeper ones, instead of leaving them alone with `clojure-ts-use-markdown-inline` and flattening them without it.
- [#174](https://github.com/clojure-emacs/clojure-ts-mode/pull/174): Speed up indentation of forms with many children, like a big `comment` form, which slowed down with the cube of their length.
- [#175](https://github.com/clojure-emacs/clojure-ts-mode/pull/175): Fix `clojure-ts-align` signalling `treesit-node-outdated` on a line that ends in a form after metadata and more than one space.

## 0.6.0 (2025-12-02)

Expand Down
27 changes: 16 additions & 11 deletions clojure-ts-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -1896,19 +1896,21 @@ children of the rich comment form are also considered as top-level."
"Return the point that represents the end of the current defun."
(treesit-node-end (treesit-defun-at-point)))

(defun clojure-ts--search-whitespace-after-next-sexp (root-node bound)
(defun clojure-ts--search-whitespace-after-next-sexp (root-node-fn bound)
"Move the point after all whitespace following the next s-expression.

Set match data group 1 to this region of whitespace and return the
point.

To move over the next s-expression, fetch the next node after the
current cursor position that is a direct child of ROOT-NODE and navigate
to its end. The most complex aspect here is handling nodes with
metadata. Some forms are represented in the syntax tree as a single
s-expression (for example, ^long my-var or ^String (str \"Hello\"
\"world\")), while other forms are two separate s-expressions (for
example, ^long 123 or ^String \"Hello\"). Expressions with two nodes
current cursor position that is a direct child of the node ROOT-NODE-FN
returns and navigate to its end. It's called again for every line, as
fixing the space after metadata on the way leaves the old node outdated.
The most complex aspect here is handling nodes with metadata. Some
forms are represented in the syntax tree as a single s-expression (for
example, ^long my-var or ^String (str \"Hello\" \"world\")), while
other forms are two separate s-expressions (for example, ^long 123 or
^String \"Hello\"). Expressions with two nodes
share some common features:

- The top-level node type is usually sym_lit
Expand All @@ -1927,7 +1929,8 @@ BOUND bounds the whitespace search."
(progn
(search-forward-regexp regex bound)
(point))
(when-let* ((cur-sexp (treesit-node-first-child-for-pos root-node (point) t)))
(when-let* ((cur-sexp (treesit-node-first-child-for-pos
(funcall root-node-fn) (point) t)))
(goto-char (treesit-node-start cur-sexp))
(if (clojure-ts--metadata-node-p cur-sexp)
(progn
Expand All @@ -1943,7 +1946,7 @@ BOUND bounds the whitespace search."
;; End-of-line, try again on next line.
(`(12) (progn
(forward-char 1)
(clojure-ts--search-whitespace-after-next-sexp root-node bound)))
(clojure-ts--search-whitespace-after-next-sexp root-node-fn bound)))
;; Closing paren, stop here.
(`(5 . ,_) nil)
;; Anything else is something to align.
Expand Down Expand Up @@ -2112,8 +2115,10 @@ between BEG and END."
(clojure-ts--point-to-align-position sexp-type node)
(align-region (point) node-end nil
`((clojure-align (regexp . ,(lambda (&optional bound _noerror)
(let ((updated-node (clojure-ts--node-from-sexp-data beg (marker-position end) sexp)))
(clojure-ts--search-whitespace-after-next-sexp updated-node bound))))
(clojure-ts--search-whitespace-after-next-sexp
(lambda ()
(clojure-ts--node-from-sexp-data beg (marker-position end) sexp))
bound)))
(group . 1)
(separate . ,clojure-ts-align-separator)
(repeat . t)))
Expand Down
10 changes: 9 additions & 1 deletion test/clojure-ts-mode-indentation-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -1482,4 +1482,12 @@ c)
:foo \"bar\"}"

"#::alias{:a 1
:bbb 2}"))
:bbb 2}")

(it "should align a line ending in a form after metadata and extra spaces"
;; Fixing the space after the metadata used to leave the node it
;; searched outdated for the next line.
(let ((clojure-ts-align-forms-automatically t))
(with-clojure-ts-buffer "{:a ^:m b\n:ccc d}"
(indent-region (point-min) (point-max))
(expect (buffer-string) :to-equal "{:a ^:m b\n :ccc d}")))))
Loading