GNU bug report logs - #78458
31.0.50; treesit.el: thing navigation functions work incorrectly with some Clojure nodes

Previous Next

Package: emacs;

Reported by: Roman Rudakov <rrudakov <at> fastmail.com>

Date: Fri, 16 May 2025 15:38:02 UTC

Severity: normal

Fixed in version 31.0.50

Done: Juri Linkov <juri <at> linkov.net>

To reply to this bug, email your comments to 78458 AT debbugs.gnu.org.
There is no need to reopen the bug first.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Fri, 16 May 2025 15:38:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Roman Rudakov <rrudakov <at> fastmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 16 May 2025 15:38:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; treesit.el: thing navigation functions work incorrectly
 with some Clojure nodes
Date: Fri, 16 May 2025 17:37:23 +0200
Reproducing issues requires installing clojure-ts-mode from NonGNU 
ELPA.

Considering the following Clojure expression:

#(-> (.-value (.-target %)))

The parsed syntax tree is:

(anon_fn_lit marker: # open: (
value: (sym_lit name: (sym_name))
value:
 (list_lit open: (
  value: (sym_lit name: (sym_name))
  value:
   (list_lit open: (
    value: (sym_lit name: (sym_name))
    value: (sym_lit name: (sym_name))
    close: ))
  close: ))
close: ))

Issue 1

1. Put the point on the "->" symbol
2. Execute M-x backward-up-list


Expected result: point at the # character, which is the beginning of
the anon_fn_lit node.

Actual result: point is between # and (

If I execute M-x backward-up-list again, point goes to the #
character.

Issue 2

1. Put the point after # on the opening paren.
2. Execute M-x forward-sexp


Expected result: either some error or point is moved to the matching
closing paren.
Actual result: point is before matching paren.

If the expression doesn't have any nested lists (for example #(+ 2 2))
then the same steps would signal a user error "No next step".

Issue 3

1. Put the point on the opening paren of the first nested list.
2. Execute M-x raise-sexp


Expected result: (.-value (.-target %))
Actual result: #(.-value (.-target %)))

Actual result also has unbalanced parenthesis.

Again, if the expression doesn't have any nested lists, executing
raise-sexp would signal an error:

treesit--forward-list-with-default: Scan error: "No more list to move 
across"

All the issues are also applicable to nodes with metadata, for
example:

^boolean (+ 2 2)

With syntax tree:

(list_lit
meta:
 (meta_lit marker: ^
  value: (sym_lit name: (sym_name)))
open: (
value: (sym_lit name: (sym_name))
value: (num_lit) value: (num_lit) close: ))



In GNU Emacs 31.0.50 (build 1, aarch64-apple-darwin24.4.0, NS
appkit-2575.50 Version 15.4.1 (Build 24E263)) of 2025-04-29 built on
macbookpro.home
Windowing system distributor 'Apple', version 10.3.2575
System Description:  macOS 15.4.1

Configured using:
'configure --disable-dependency-tracking --disable-silent-rules
--enable-locallisppath=/opt/homebrew/share/emacs/site-lisp
--infodir=/opt/homebrew/Cellar/emacs-plus <at> 31/31.0.50/share/info/emacs
--prefix=/opt/homebrew/Cellar/emacs-plus <at> 31/31.0.50
--with-native-compilation=aot --with-xml2 --with-gnutls
--without-compress-install --without-dbus --without-imagemagick
--with-modules --with-rsvg --with-webp --without-pop --with-ns
--disable-ns-self-contained 'CFLAGS=-O2 -DFD_SETSIZE=10000
-DDARWIN_UNLIMITED_SELECT -I/opt/homebrew/opt/sqlite/include
-I/opt/homebrew/opt/gcc/include 
-I/opt/homebrew/opt/libgccjit/include'
'LDFLAGS=-L/opt/homebrew/opt/sqlite/lib -L/opt/homebrew/lib/gcc/14
-I/opt/homebrew/opt/gcc/include 
-I/opt/homebrew/opt/libgccjit/include''
Configured features:
ACL GIF GLIB GMP GNUTLS JPEG LCMS2 LIBXML2 MODULES NATIVE_COMP NOTIFY
KQUEUE NS PDUMPER PNG RSVG SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS
TREE_SITTER WEBP XIM ZLIB
Important settings:
 value of $LANG: en_US.UTF-8
 locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
 TeX-PDF-mode: t
 global-git-commit-mode: t
 magit-auto-revert-mode: t
 idle-highlight-mode: t
 subword-mode: t
 yas-minor-mode: t
 hl-todo-mode: t
 flymake-mode: t
 server-mode: t
 pdf-occur-global-minor-mode: t
 mu4e-column-faces-mode: t
 mu4e-modeline-mode: t
 auto-insert-mode: t
 electric-pair-mode: t
 org-roam-db-autosync-mode: t
 minions-mode: t
 repeat-mode: t
 save-place-mode: t
 minibuffer-electric-default-mode: t
 savehist-mode: t
 recentf-mode: t
 global-auto-revert-mode: t
 global-hl-line-mode: t
 apheleia-mode: t
 global-eldoc-mode: t
 eldoc-mode: t
 show-paren-mode: t
 electric-indent-mode: t
 mouse-wheel-mode: t
 tab-bar-mode: t
 menu-bar-mode: t
 file-name-shadow-mode: t
 global-font-lock-mode: t
 font-lock-mode: t
 blink-cursor-mode: t
 window-divider-mode: t
 minibuffer-regexp-mode: t
 column-number-mode: t
 line-number-mode: t
 transient-mark-mode: t
 auto-composition-mode: t
 auto-encryption-mode: t
 auto-compression-mode: t

Load-path shadows:
/Users/rrudakov/.config/emacs/elpa/ef-themes-1.10.0/theme-loaddefs 
hides 
/Users/rrudakov/.config/emacs/elpa/modus-themes-4.7.0/theme-loaddefs
/Users/rrudakov/.config/emacs/elpa/magit-4.3.2/magit-autorevert hides 
/Users/rrudakov/.config/emacs/elpa/magit-section-4.3.2/magit-autorevert
/Users/rrudakov/.config/emacs/elpa/transient-0.8.8/transient hides 
/opt/homebrew/Cellar/emacs-plus <at> 31/31.0.50/share/emacs/31.0.50/lisp/transient
/Users/rrudakov/.config/emacs/elpa/ef-themes-1.10.0/theme-loaddefs 
hides 
/opt/homebrew/Cellar/emacs-plus <at> 31/31.0.50/share/emacs/31.0.50/lisp/theme-loaddefs

Features:
(shadow emacsbug flyspell-correct reftex-dcr reftex reftex-loaddefs
reftex-vars tex-fold preview font-latex latex latex-flymake tex-ispell
tex-style tex texmathp auctex tex-mode google-c-style plantuml-mode
artist picture reporter find-dired
clojure-ts-mode-refactor-add-arity-test test-helper buttercup ert ewoc
debug backtrace buttercup-compat magit-extras goto-addr cider-ns
apheleia apheleia-rcs apheleia-dp apheleia-formatters apheleia-utils
apheleia-log apheleia-formatter-context qp cal-iso pcmpl-unix 
pcmpl-gnu
sort smiley gnus-cite mm-archive mail-extr textsec uni-scripts
idna-mapping uni-confusable textsec-check misc emacs-everywhere vc-hg
vc-svn bug-reference tramp-cache time-stamp shortdoc cl-print misearch
multi-isearch org-goto help-fns radix-tree cal-move markdown-mode
edit-indirect face-remap magit-bookmark magit-submodule magit-blame
magit-stash magit-reflog magit-bisect magit-push magit-pull 
magit-fetch
magit-clone magit-remote magit-commit magit-sequence magit-notes
magit-worktree magit-tag magit-merge magit-branch magit-reset
magit-files magit-refs magit-status magit magit-repos magit-apply
magit-wip magit-log magit-diff smerge-mode diff git-commit log-edit
pcvs-util add-log magit-core magit-autorevert magit-margin
magit-transient magit-process with-editor magit-mode elp magit-git
magit-base which-func vc-git diff-mode track-changes flymake-kondor
clj-refactor hydra lv inflections mc-hide-unmatched-lines-mode
mc-mark-more sgml-mode mc-cycle-cursors multiple-cursors-core rect
paredit cider tramp-sh cider-debug cider-browse-ns cider-mode
cider-xref-backend cider-find cider-completion cider-profile
cider-inspector cider-eval cider-jar arc-mode archive-mode
clojure-ts-mode cider-repl-history pulse cider-repl cider-resolve
cider-test cider-overlays cider-stacktrace cider-doc cider-browse-spec
cider-clojuredocs cider-eldoc cider-docstring cider-client 
cider-common
xref cider-completion-context cider-connection cider-popup
sesman-browser nrepl-client tramp trampver tramp-integration
tramp-message tramp-compat tramp-loaddefs sesman queue nrepl-dict
cider-util spinner parseedn parseclj-parser parseclj-lex 
parseclj-alist
clojure-mode align idle-highlight-mode cap-words superword subword
yasnippet ef-maris-dark-theme ef-themes hl-todo checkdoc lisp-mnt
flymake view cus-start alert log4e gntp server github org-git
ghub-graphql treepy gsexp ghub url-http url-gw nsm url-auth
google-translate-smooth-ui google-translate-core-ui facemenu color 
popup
google-translate-core google-translate-backend use-package-ensure
pdf-occur tablist tablist-filter semantic/wisent/comp semantic/wisent
semantic/wisent/wisent semantic/util-modes semantic/util semantic
semantic/tag semantic/lex semantic/fw mode-local cedet pdf-isearch
let-alist pdf-misc pdf-tools pdf-view jka-compr pdf-cache pdf-info tq
pdf-util pdf-macs image-mode exif ob-restclient restclient
mu4e-column-faces mu4e-icalendar gnus-icalendar icalendar mu4e 
mu4e-org
mu4e-notification notifications mu4e-main smtpmail mu4e-view
mu4e-mime-parts mu4e-headers mu4e-thread mu4e-actions mu4e-compose
mu4e-draft gnus-msg mu4e-search mu4e-lists mu4e-bookmarks mu4e-mark
mu4e-message flow-fill mu4e-contacts mu4e-update mu4e-folders
mu4e-context mu4e-query-items mu4e-server mu4e-modeline mu4e-vars
mu4e-helpers mu4e-config mu4e-window bookmark ido mu4e-obsolete 
nix-mode
ffap nix-repl nix-shell nix-store nix-log nix-instantiate nix-shebang
nix-format nix yaml-ts-mode dockerfile-ts-mode rust-ts-mode
typescript-ts-mode js c-ts-common imenu cc-mode cc-fonts cc-guess
cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs 
vlf-setup
vlf vlf-base vlf-tune autoinsert rg files-x vc vc-dispatcher
rg-info-hack rg-menu transient edmacro kmacro rg-ibuffer rg-result
wgrep-rg wgrep rg-history rg-header ibuf-ext ibuffer ibuffer-loaddefs
grep compile elec-pair emacsql-sqlite-builtin org-roam-migrate
org-roam-log org-roam-mode org-roam-capture org-roam-id org-roam-node
crm org-roam-db org-roam-utils org-roam-compat org-roam org-capture
emacsql-sqlite emacsql emacsql-compiler magit-section benchmark
cursor-sensor llama comp comp-cstr dash async ob-async ob-plantuml
ob-ditaa ob-clojure ob-haskell ob-sqlite ob-shell shell ob-sql 
ob-python
python project pcase org-clock appt diary-lib diary-loaddefs
org-duration comp-run comp-common flyspell ispell oc-basic bibtex
disp-table ol-info ol-gnus nnselect gnus-art mm-uu mml2015 mm-view
mml-smime smime gnutls dig gnus-sum shr-tag-pre-highlight
language-detection shr pixel-fill kinsoku url-file svg dom gnus-group
gnus-undo gnus-start gnus-dbus dbus xml gnus-cloud nnimap nnmail
mail-source utf7 nnoo parse-time iso8601 gnus-spec gnus-int gnus-range
message sendmail yank-media puny dired dired-loaddefs rfc822 mml 
mml-sec
epa derived epg rfc6068 epg-config mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047 rfc2045 ietf-drums mailabbrev gmm-utils
mailheader gnus-win gnus nnheader gnus-util text-property-search
mail-utils range mm-util mail-prsvr ox-gfm ox-md ox-odt rng-loc 
rng-uri
rng-parse rng-match rng-dt rng-util rng-pttrn nxml-parse nxml-ns
nxml-enc xmltok nxml-util ox-latex ox-icalendar ox-html table ox-ascii
ox-publish ox org-attach org-agenda org-element org-persist org-id
org-element-ast inline avl-tree generator org-refile org ob ob-tangle
ob-ref ob-lob ob-table ob-exp org-macro org-src sh-script smie treesit
executable ob-comint org-pcomplete pcomplete org-list org-footnote
org-faces org-entities time-date noutline outline org-version
ob-emacs-lisp ob-core ob-eval org-cycle org-table org-keys oc
org-loaddefs thingatpt find-func cal-menu calendar cal-loaddefs ol
org-fold org-fold-core org-compat org-macs format-spec
exec-path-from-shell minions compat warnings repeat hippie-exp comint
ansi-osc ansi-color ring advice saveplace minibuf-eldef savehist 
recentf
tree-widget cl-extra help-mode autorevert filenotify use-package-core
easy-mmode hl-line rx finder-inf package browse-url xdg url url-proxy
url-privacy url-expand url-methods url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x
map byte-opt gv bytecomp byte-compile url-vars info
add-node-modules-path-autoloads alert-autoloads apheleia-autoloads
auctex-autoloads tex-site buttercup-autoloads clj-refactor-autoloads
cider-autoloads clojure-mode-autoloads clojure-ts-mode-autoloads
csv-mode-autoloads debbugs-autoloads dired-git-info-autoloads
dired-subtree-autoloads dired-hacks-utils-autoloads direnv-autoloads
dtrt-indent-autoloads edit-indirect-autoloads ef-themes-autoloads
elfeed-autoloads emacs-everywhere-autoloads emmet-mode-autoloads
exec-path-from-shell-autoloads expand-region-autoloads
flymake-kondor-autoloads flyspell-correct-autoloads ghub-autoloads
git-link-autoloads gitignore-templates-autoloads gntp-autoloads
google-c-style-autoloads google-translate-autoloads
groovy-mode-autoloads haskell-mode-autoloads hl-todo-autoloads
hydra-autoloads idle-highlight-mode-autoloads inflections-autoloads
log4e-autoloads logview-autoloads datetime-autoloads extmap-autoloads
lua-mode-autoloads lv-autoloads magit-autoloads 
markdown-mode-autoloads
minions-autoloads modus-themes-autoloads mu4e-column-faces-autoloads
multiple-cursors-autoloads nginx-mode-autoloads nix-mode-autoloads
nov-autoloads esxml-autoloads ob-async-autoloads async-autoloads
ob-restclient-autoloads org-roam-autoloads magit-section-autoloads
llama-autoloads emacsql-autoloads org-tree-slide-autoloads
ox-jira-autoloads ox-slack-autoloads ox-gfm-autoloads 
paredit-autoloads
parseedn-autoloads parseclj-autoloads password-store-otp-autoloads
password-store-autoloads pdf-tools-autoloads 
pip-requirements-autoloads
pkgbuild-mode-autoloads plantuml-mode-autoloads dash-autoloads
popup-autoloads pyvenv-autoloads queue-autoloads 
rainbow-mode-autoloads
restclient-autoloads rg-autoloads s-autoloads sesman-autoloads
shr-tag-pre-highlight-autoloads language-detection-autoloads
sly-autoloads spinner-autoloads sql-indent-autoloads
ssh-config-mode-autoloads tablist-autoloads telega-autoloads
transient-autoloads treepy-autoloads vimrc-mode-autoloads
visual-fill-column-autoloads vlf-autoloads web-mode-autoloads
wgrep-autoloads with-editor-autoloads yasnippet-autoloads cus-edit pp
cus-load icons wid-edit cl-loaddefs cl-lib rmc iso-transl tooltip 
cconv
eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type
elisp-mode mwheel term/ns-win ns-win ucs-normalize mule-util
term/common-win tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode 
register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet 
lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj 
charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray 
oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable 
backquote
threads kqueue cocoa ns lcms2 multi-tty make-network-process
tty-child-frames native-compile emacs)

Memory information:
((conses 16 1719864 397462) (symbols 48 72397 42)
(strings 32 381592 20509) (string-bytes 1 12071862)
(vectors 16 317198) (vector-slots 8 3093109 175837)
(floats 8 91865 4975) (intervals 56 61124 11438) (buffers 992 76))

-- 
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Fri, 16 May 2025 16:04:04 GMT) Full text and rfc822 format available.

Message #8 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Roman Rudakov <rrudakov <at> fastmail.com>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Fri, 16 May 2025 19:02: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'.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Fri, 16 May 2025 16:19:04 GMT) Full text and rfc822 format available.

Message #11 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: Juri Linkov <juri <at> linkov.net>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Fri, 16 May 2025 18:18:27 +0200
Juri Linkov <juri <at> linkov.net> writes:

>> 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?

--
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 07:16:01 GMT) Full text and rfc822 format available.

Message #14 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Roman Rudakov <rrudakov <at> fastmail.com>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
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




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 08:16:02 GMT) Full text and rfc822 format available.

Message #17 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: Juri Linkov <juri <at> linkov.net>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Mon, 19 May 2025 10:15:40 +0200
Juri Linkov <juri <at> linkov.net> writes:

>>>> 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
Thanks Juri. I tried your patch and for some reason it doesn't solve 
the issue neither with 'raise-sexp' nor with 'C-M-f' navigation. The 
point is moved from:

#|(-> (.-value (.-target %)))

to

#(-> (.-value (.-target %))|)

and 'raise-sexp' called from:

#(-> |(.-value (.-target %)))

produces:

#(.-value (.-target %)))

Quick debugging confirmed that when the point is between # and ( the 
matched "thing" is 'sexp-default'.
--
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 17:52:02 GMT) Full text and rfc822 format available.

Message #20 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Roman Rudakov <rrudakov <at> fastmail.com>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Mon, 19 May 2025 20:48:25 +0300
[Message part 1 (text/plain, inline)]
>> +     (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")))))
> Thanks Juri. I tried your patch and for some reason it doesn't solve the
> issue neither with 'raise-sexp' nor with 'C-M-f' navigation. The point is
> moved from:
>
> #|(-> (.-value (.-target %)))
>
> to
>
> #(-> (.-value (.-target %))|)

I tested that this patch fixes 'C-M-f' navigation where point moves to

#(-> (.-value (.-target %)))|

> and 'raise-sexp' called from:
>
> #(-> |(.-value (.-target %)))
>
> produces:
>
> #(.-value (.-target %)))

Indeed, it didn't fix this case.  For down/up-list it needs
to use 'sexp' thing instead of 'list' thing.  Probably the simplest
setting would be to redefine down-list-function/up-list-function.

Ok, here is a complete tested patch that fixes all your test cases:

[clojure-ts-mode-sexp.patch (text/x-diff, inline)]
diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el
index 8b6bca7..6ae8e16 100644
--- a/clojure-ts-mode.el
+++ b/clojure-ts-mode.el
@@ -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
@@ -2601,6 +2607,15 @@ clojure-ts-mode
                 0
                 t)
 
+      (setq-local down-list-function
+                  (lambda (&optional arg)
+                    (let ((treesit-sexp-type-regexp 'sexp))
+                      (treesit-down-list arg))))
+      (setq-local up-list-function
+                  (lambda (&optional arg escape-strings no-syntax-crossing)
+                    (let ((treesit-sexp-type-regexp 'sexp))
+                      (treesit-up-list arg escape-strings no-syntax-crossing))))
+
       ;; Workaround for treesit-transpose-sexps not correctly working with
       ;; treesit-thing-settings on Emacs 30.
       ;; Once treesit-transpose-sexps it working again this can be removed

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 18:22:03 GMT) Full text and rfc822 format available.

Message #23 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: Juri Linkov <juri <at> linkov.net>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Mon, 19 May 2025 20:20:51 +0200
Juri Linkov <juri <at> linkov.net> writes:

>>> +     (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")))))
>> Thanks Juri. I tried your patch and for some reason it doesn't 
>> solve the
>> issue neither with 'raise-sexp' nor with 'C-M-f' navigation. The 
>> point is
>> moved from:
>>
>> #|(-> (.-value (.-target %)))
>>
>> to
>>
>> #(-> (.-value (.-target %))|)
>
> I tested that this patch fixes 'C-M-f' navigation where point moves 
> to
>
> #(-> (.-value (.-target %)))|
>
>> and 'raise-sexp' called from:
>>
>> #(-> |(.-value (.-target %)))
>>
>> produces:
>>
>> #(.-value (.-target %)))
>
> Indeed, it didn't fix this case.  For down/up-list it needs
> to use 'sexp' thing instead of 'list' thing.  Probably the simplest
> setting would be to redefine down-list-function/up-list-function.
>
> Ok, here is a complete tested patch that fixes all your test cases:
>
> [2. text/x-diff; clojure-ts-mode-sexp.patch]
> diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el
> index 8b6bca7..6ae8e16 100644
> --- a/clojure-ts-mode.el
> +++ b/clojure-ts-mode.el
> @@ -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
> @@ -2601,6 +2607,15 @@ clojure-ts-mode
>                  0
>                  t)
>
> +      (setq-local down-list-function
> +                  (lambda (&optional arg)
> +                    (let ((treesit-sexp-type-regexp 'sexp))
> +                      (treesit-down-list arg))))
> +      (setq-local up-list-function
> +                  (lambda (&optional arg escape-strings 
> no-syntax-crossing)
> +                    (let ((treesit-sexp-type-regexp 'sexp))
> +                      (treesit-up-list arg escape-strings 
> no-syntax-crossing))))
> +
>        ;; Workaround for treesit-transpose-sexps not correctly 
>        working with
>        ;; treesit-thing-settings on Emacs 30.
>        ;; Once treesit-transpose-sexps it working again this can be 
>        removed
Thank you very much for the patch Juri. It indeed solves all of the 
problems I mentioned.  However while I was testing the patch I noticed 
that the 'down-list' function behaves a bit odd. If I call it multiple 
times starting from the beginning of the line it moves the point to 
the following positions:

#|(-> (.-value (.-target %)))
#(->| (.-value (.-target %)))
#(-> (.-value| (.-target %)))
#(-> (.-value| (|.-target %)))
#(-> (.-value| (.-target| %)))
#(-> (.-value| (.-target %|)))

While it would be more logical to have:

#(|-> (.-value (.-target %)))
#(-> (|.-value (.-target %)))
#(-> (.-value (|.-target %)))

--
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 18:58:01 GMT) Full text and rfc822 format available.

Message #26 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Roman Rudakov <rrudakov <at> fastmail.com>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Mon, 19 May 2025 21:50:37 +0300
>> +      (setq-local down-list-function
>> +                  (lambda (&optional arg)
>> +                    (let ((treesit-sexp-type-regexp 'sexp))
>> +                      (treesit-down-list arg))))
>> +      (setq-local up-list-function
>> +                  (lambda (&optional arg escape-strings no-syntax-crossing)
>> +                    (let ((treesit-sexp-type-regexp 'sexp))
>> +                      (treesit-up-list arg escape-strings no-syntax-crossing))))
>> +
>>        ;; Workaround for treesit-transpose-sexps not correctly working with
>>        ;; treesit-thing-settings on Emacs 30.
>>        ;; Once treesit-transpose-sexps it working again this can be removed
> Thank you very much for the patch Juri. It indeed solves all of the
> problems I mentioned.  However while I was testing the patch I noticed that
> the 'down-list' function behaves a bit odd. If I call it multiple times
> starting from the beginning of the line it moves the point to the following
> positions:
>
> #|(-> (.-value (.-target %)))
> #(->| (.-value (.-target %)))
> #(-> (.-value| (.-target %)))
> #(-> (.-value| (|.-target %)))
> #(-> (.-value| (.-target| %)))
> #(-> (.-value| (.-target %|)))

Then please remove '(setq-local down-list-function ..' from the patch,
it's not needed.

> While it would be more logical to have:
>
> #(|-> (.-value (.-target %)))
> #(-> (|.-value (.-target %)))
> #(-> (.-value (|.-target %)))

Without redefining 'down-list-function'
the 'down-list' function behaves like above.

But we can do nothing to fix the first step:

#|(-> (.-value (.-target %)))

because using treesit nodes, "#" is a child node of
'anon_fn_lit', so 'down-list' goes after it.

Since the treesit grammar can't handle this case,
you could try to use the default function by

  (setq-local down-list-function nil)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 19:17:03 GMT) Full text and rfc822 format available.

Message #29 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: Juri Linkov <juri <at> linkov.net>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Mon, 19 May 2025 21:15:53 +0200
Juri Linkov <juri <at> linkov.net> writes:

>>> +      (setq-local down-list-function
>>> +                  (lambda (&optional arg)
>>> +                    (let ((treesit-sexp-type-regexp 'sexp))
>>> +                      (treesit-down-list arg))))
>>> +      (setq-local up-list-function
>>> +                  (lambda (&optional arg escape-strings 
>>> no-syntax-crossing)
>>> +                    (let ((treesit-sexp-type-regexp 'sexp))
>>> +                      (treesit-up-list arg escape-strings 
>>> no-syntax-crossing))))
>>> +
>>>        ;; Workaround for treesit-transpose-sexps not correctly 
>>>        working with
>>>        ;; treesit-thing-settings on Emacs 30.
>>>        ;; Once treesit-transpose-sexps it working again this can 
>>>        be removed
>> Thank you very much for the patch Juri. It indeed solves all of the
>> problems I mentioned.  However while I was testing the patch I 
>> noticed that
>> the 'down-list' function behaves a bit odd. If I call it multiple 
>> times
>> starting from the beginning of the line it moves the point to the 
>> following
>> positions:
>>
>> #|(-> (.-value (.-target %)))
>> #(->| (.-value (.-target %)))
>> #(-> (.-value| (.-target %)))
>> #(-> (.-value| (|.-target %)))
>> #(-> (.-value| (.-target| %)))
>> #(-> (.-value| (.-target %|)))
>
> Then please remove '(setq-local down-list-function ..' from the 
> patch,
> it's not needed.
>
>> While it would be more logical to have:
>>
>> #(|-> (.-value (.-target %)))
>> #(-> (|.-value (.-target %)))
>> #(-> (.-value (|.-target %)))
>
> Without redefining 'down-list-function'
> the 'down-list' function behaves like above.
>
> But we can do nothing to fix the first step:
>
> #|(-> (.-value (.-target %)))
>
> because using treesit nodes, "#" is a child node of
> 'anon_fn_lit', so 'down-list' goes after it.
>
> Since the treesit grammar can't handle this case,
> you could try to use the default function by
>
>   (setq-local down-list-function nil)
Thank you! That is very helpful. I was able to use your patch with 
small modifications to make it work for function literals and sets 
(that have the same # marker node).  I'll try to discuss with the 
author of the grammar possibility to modify it to have just one 
'open:' node instead of two.

I think this bug can be closed now.
--
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Mon, 19 May 2025 19:31:02 GMT) Full text and rfc822 format available.

Message #32 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: Juri Linkov <juri <at> linkov.net>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Mon, 19 May 2025 21:29:53 +0200
Roman Rudakov <rrudakov <at> fastmail.com> writes:

> Juri Linkov <juri <at> linkov.net> writes:
>
>>>> +      (setq-local down-list-function
>>>> +                  (lambda (&optional arg)
>>>> +                    (let ((treesit-sexp-type-regexp 'sexp))
>>>> +                      (treesit-down-list arg))))
>>>> +      (setq-local up-list-function
>>>> +                  (lambda (&optional arg escape-strings
>>>> no-syntax-crossing)
>>>> +                    (let ((treesit-sexp-type-regexp 'sexp))
>>>> +                      (treesit-up-list arg escape-strings
>>>> no-syntax-crossing))))
>>>> +
>>>>        ;; Workaround for treesit-transpose-sexps not correctly
>>>>        working with
>>>>        ;; treesit-thing-settings on Emacs 30.
>>>>        ;; Once treesit-transpose-sexps it working again this can
>>>>        be removed
>>> Thank you very much for the patch Juri. It indeed solves all of 
>>> the
>>> problems I mentioned.  However while I was testing the patch I
>>> noticed that
>>> the 'down-list' function behaves a bit odd. If I call it multiple
>>> times
>>> starting from the beginning of the line it moves the point to the
>>> following
>>> positions:
>>>
>>> #|(-> (.-value (.-target %)))
>>> #(->| (.-value (.-target %)))
>>> #(-> (.-value| (.-target %)))
>>> #(-> (.-value| (|.-target %)))
>>> #(-> (.-value| (.-target| %)))
>>> #(-> (.-value| (.-target %|)))
>>
>> Then please remove '(setq-local down-list-function ..' from the
>> patch,
>> it's not needed.
>>
>>> While it would be more logical to have:
>>>
>>> #(|-> (.-value (.-target %)))
>>> #(-> (|.-value (.-target %)))
>>> #(-> (.-value (|.-target %)))
>>
>> Without redefining 'down-list-function'
>> the 'down-list' function behaves like above.
>>
>> But we can do nothing to fix the first step:
>>
>> #|(-> (.-value (.-target %)))
>>
>> because using treesit nodes, "#" is a child node of
>> 'anon_fn_lit', so 'down-list' goes after it.
>>
>> Since the treesit grammar can't handle this case,
>> you could try to use the default function by
>>
>>   (setq-local down-list-function nil)
> Thank you! That is very helpful. I was able to use your patch with
> small modifications to make it work for function literals and sets
> (that have the same # marker node).  I'll try to discuss with the
> author of the grammar possibility to modify it to have just one
> 'open:' node instead of two.
>
> I think this bug can be closed now.
One more question.  Will the trick with defining 'sexp-default' work 
in Emacs 30?  Or is it a new "thing" which is only available in 
master?
--
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Tue, 20 May 2025 06:57:02 GMT) Full text and rfc822 format available.

Message #35 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Roman Rudakov <rrudakov <at> fastmail.com>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Tue, 20 May 2025 09:49:32 +0300
close 78458 31.0.50
thanks

>>> Since the treesit grammar can't handle this case,
>>> you could try to use the default function by
>>>
>>>   (setq-local down-list-function nil)
>> Thank you! That is very helpful. I was able to use your patch with
>> small modifications to make it work for function literals and sets
>> (that have the same # marker node).  I'll try to discuss with the
>> author of the grammar possibility to modify it to have just one
>> 'open:' node instead of two.

One node instead of two would be nicer for such things as
show-paren-mode.  But probably it won't much of help for navigation.
For example, bash-ts-mode still requires the trick with 'sexp-default'
even when the bash grammar defines "$(" as a single node.

>> I think this bug can be closed now.

Ok, so closing now.

> One more question.  Will the trick with defining 'sexp-default' work in
> Emacs 30?  Or is it a new "thing" which is only available in master?

Alas, 'sexp-default' is available only in master.




bug marked as fixed in version 31.0.50, send any further explanations to 78458 <at> debbugs.gnu.org and Roman Rudakov <rrudakov <at> fastmail.com> Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Tue, 20 May 2025 06:57:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Tue, 20 May 2025 08:51:02 GMT) Full text and rfc822 format available.

Message #40 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Roman Rudakov <rrudakov <at> fastmail.com>
To: Juri Linkov <juri <at> linkov.net>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Tue, 20 May 2025 10:50:24 +0200
Juri Linkov <juri <at> linkov.net> writes:

> close 78458 31.0.50
> thanks
>
>>>> Since the treesit grammar can't handle this case,
>>>> you could try to use the default function by
>>>>
>>>>   (setq-local down-list-function nil)
>>> Thank you! That is very helpful. I was able to use your patch with
>>> small modifications to make it work for function literals and sets
>>> (that have the same # marker node).  I'll try to discuss with the
>>> author of the grammar possibility to modify it to have just one
>>> 'open:' node instead of two.

I've checked bash-ts-mode, and 'down-list' function jumps to the 
proper place (right after opening paren), so I guess having one node 
instead of two would help with navigation a little bit.

>
> One node instead of two would be nicer for such things as
> show-paren-mode.  But probably it won't much of help for navigation.
> For example, bash-ts-mode still requires the trick with 
> 'sexp-default'
> even when the bash grammar defines "$(" as a single node.
>
>>> I think this bug can be closed now.
>
> Ok, so closing now.
>
>> One more question.  Will the trick with defining 'sexp-default' 
>> work in
>> Emacs 30?  Or is it a new "thing" which is only available in 
>> master?
>
> Alas, 'sexp-default' is available only in master.

Thanks for confirmation.
--
Best regards, Roman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78458; Package emacs. (Tue, 20 May 2025 16:35:02 GMT) Full text and rfc822 format available.

Message #43 received at 78458 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Roman Rudakov <rrudakov <at> fastmail.com>
Cc: 78458 <at> debbugs.gnu.org
Subject: Re: bug#78458: 31.0.50; treesit.el: thing navigation functions work
 incorrectly with some Clojure nodes
Date: Tue, 20 May 2025 19:32:19 +0300
>>>> I'll try to discuss with the author of the grammar possibility
>>>> to modify it to have just one 'open:' node instead of two.
>>
>> One node instead of two would be nicer for such things as
>> show-paren-mode.  But probably it won't much of help for navigation.
>> For example, bash-ts-mode still requires the trick with 'sexp-default'
>> even when the bash grammar defines "$(" as a single node.
>
> I've checked bash-ts-mode, and 'down-list' function jumps to the proper
> place (right after opening paren), so I guess having one node instead of
> two would help with navigation a little bit.

Indeed, one node will help to fix 'down-list' using 'treesit-down-list'.




This bug report was last modified 28 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.