Subject: bug#78458: 31.0.50; treesit.el: thing navigation functions work incorrectly with some Clojure nodes

From: Juri Linkov <[email-masked]>
Date: Mon, 19 May 2025 09:58:40 +0300

>>> Reproducing issues requires installing clojure-ts-mode from NonGNU ELPA.
>>
>> Please also try all these test cases
>> after calling 'treesit-cycle-sexp-type'.
> This makes it somewhat better.
>
> There is still some weird behavior (I guess it's mostly related to the
> Clojure grammar itself):
>
> #|(-> (.-value (.-target %)))
>
> If the point is at "|", calling "forward-sexp" moves it to:
>
> #(->| (.-value (.-target %)))
>
> And executing M-x raise-sexp produces:
>
> (->
>
> How can I set the default "cycle type" programmatically for a major mode?

Programmatically you can set it by just adding '(treesit-cycle-sexp-type)'
to the end of 'clojure-ts-mode'.  Then theoretically it requires
more changes in 'clojure-ts--sexp-nodes'.  But now I realized that
no definition can match "(" with ")" when point is between "#" and "(":

  (anon_fn_lit marker: "#" open: "("

So the right solution is without 'treesit-cycle-sexp-type'
but with using 'sexp-default':

@@ -1549,6 +1549,12 @@ clojure-ts--thing-settings
   `((clojure
      (sexp ,(regexp-opt clojure-ts--sexp-nodes))
      (list ,(regexp-opt clojure-ts--list-nodes))
+     (sexp-default
+      ;; For `C-M-f' in "#|(a)"
+      ("(" . ,(lambda (node)
+                 (and (eq (char-before (point)) ?\#)
+                      (equal (treesit-node-type (treesit-node-parent node))
+                             "anon_fn_lit")))))
      (text ,(regexp-opt '("comment")))
      (defun ,#'clojure-ts--defun-node-p))
     (when clojure-ts-use-markdown-inline