Subject: bug#68664: 29.1.50; treesit defun commands broken with nested functions

From: Troy Brown <[email-masked]>
Date: Wed, 24 Jan 2024 09:13:07 -0500

On Wed, Jan 24, 2024 at 1:29 AM Yuan Fu <[email-masked]> wrote:
>
> The behavior is expected. But I can see that it doesn’t match your expectations. The logic behind the current behavior is to first move between siblings in the same level; if there’s no sibling to move across anymore, move to the beginning/end of the immediate parent, and so on.
>
> To get the behavior you want, we would need to add a fourth defun navigation tactic, in addition to the existing three: nested, top-level, and restricted.
>
> If you are interested and able, maybe you can look into adding it to treesit--navigate-thing or treesit-beginning/end-of-defun?
>
> Yuan

I find it quite odd that this is the expected behavior.  Per the Emacs
manual (section "Moving by Defuns"), I expected the point to be moved
to the "innermost defun around point", since treesit-defun-tactic is
set to "nested", as that is precisely what is documented there.  I
interpret "innermost defun around point" to mean the innermost defun
that encompasses point.  Additionally, the documentation strings for
treesit-beginning-of-defun and treesit-end-of-defun indicate that they
are a tree-sitter equivalent of the beginning-of-defun and
end-of-defun commands respectively.  If so, and since they are mapped
to the same key bindings in the tree-sitter modes, shouldn't the
expectation be that they behave the same way as the non-tree-sitter
commands?  If not, people transitioning between the non-tree-sitter
mode and the tree-sitter mode are in for a surprise when the commands
behave differently.

With the current behavior there is no way to move the point directly
to the beginning of the function without moving through all of the
nested functions first, which could be significant.  When you say the
behavior is to "move between siblings in the same level", should the
level refer to where point is, or to the level corresponding to the
function encompassing the point?  I think it probably makes sense to
move between siblings if you are at a function boundary (there is a
function immediately before or after the point), but if you are
already deep in a function, I think it makes sense to first move to
that function's begin/end before attempting to move between siblings.
I believe this behavior would be consistent with the non-tree-sitter
modes and expectations based on the description in the manual.