Subject: Re: bug#73404: 30.0.50; [forward/kill/etc]-sexp commands do not behave as expected in tree-sitter modes

From: Juri Linkov <[email-masked]>
Date: Wed, 25 Dec 2024 19:36:48 +0200

>> Probably we could use just such heuristics that 'down-list' should skip
>> the first node of the balanced pair.  This should work for most ts-modes.
>> 
>> For example, for 'jsx_element' the first child to skip is 'jsx_opening_element'.
>> For 'argument_list' the first child to skip is an anonymous node "(".
>> For 'statement_block' the first child to skip is an anonymous node "{“.
>
> Yes, that should work for the vast majority of grammars. I can’t think
> of an counter example other than for_statment in tree-sitter-c.

Indeed, the 'for_statement' is a hard problem, and I see
no good solution.  I already encountered in different languages
the same problem that you described:

> We might also want a way to jump from pair-open to pair-end. Going to
> pair-open’s parent’s end will be almost always correct. (Except for the
> grammars that do weird stuff, like tree-sitter-c’s for statement, the
> condition is not a node by itself, but split into opening parentheses,
> initializer, loop condition, increment, closing paren, all of which direct
> child of the for_statement, not grouped into a condition node.)

Maybe indeed worth to try defining pair-open and pair-end as
some children nodes of the 'for_statement', i.e. only the opening paren
and the closing paren.  Something like (completely untested):

(and (member (treesit-node-text node) '("(" ")"))
     (equal (treesit-node-type (treesit-node-parent node)) "for_statement"))