-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include treesitter objects in select mode #2802
Conversation
I gave this a try and I don't see it being consistent with
instead of
(where |
Thanks for taking a look at this. However, I've run into a bigger issue - when our cursor is at the start of a function block, I can't determine what the user intended from the available information in Specifically, when the range faces backwards and user selects forwards this could mean they are extending a first selection further forward (which the code currently handles correctly), or that they are selecting backwards, and want to deselect the most recently encountered block (which presently breaks and acts as if it were the first selection). Insofar as the directions of the range and new range and concerned these two cases look the same, and without actively tracking selected treesitter objects (or at least having their selections placed in the recent action buffer) I'm currently drawing a blank on how to differentiate them further. If any obvious solution pokes its head out at you reading this, please advise, otherwise I think I have more or less discovered why this feature didn't already exist.. :) |
Actually I think my comment may have been wrong: those extensions were correct based on the head and anchor of the selection range. The overall behavior is a bit surprising though and I think it's because
where @sudormrfbin I see you in the blame for helix/helix-core/src/movement.rs Lines 436 to 437 in c107f4e
What do you think about having the tree-sitter motions not always return the selection backwards? |
I considered this, and came to a similar conclusion about treesitter selects always putting the cursor first. I did test it earlier without touching While I agree with fixing them to match paragraph selects in respecting the direction they were made in, it seems the edge case can still take place quite easily by selecting several function blocks backwards and then selecting one forwards (as one might to deselect). This again gives us no way to differentiate from an initial forward selection and extension - so I fear there's still going to be a missing piece of context for implementing this. |
to use your earlier example:
because it looks identical to us, context wise (ie. based on directional comparison between old and new ranges), to when we use Hopefully this makes what I'm saying about backwards then forwards selecting a bit clearer. |
I wrote it that way with the intention of making it easier to see (for example in the function object) the function declaration rather than the last statement in the function definition. Now that I think about it, the current behavior of next/prev treesitter object is very different from next/prev word, paragraph, etc:
If these two inconsistencies can be fixed, I think the select mode treesitter variants can be implemented easily without the edge cases similar to how select mode |
I have implemented the As far as I can tell from testing, this patch now works properly and treesitter select should be semantically in line with other select modes 😄 Please let me know if you find anything else out of the ordinary. |
Sweet this is looking pretty good! There's one case I think is a bit awkward:
going backward (
It's easy to work around this by trimming whitespace from the selection with
instead. What do you think? |
Looking into this now, I'm not sure there is a better way than auto filtering whitespace for this specific movement - seems like TS will plough on accruing whitespace in its current node until it encounters something it can decide is a new one. I'll see what I come up with. |
I've added the whitespace clipping - it definitely feels cleaner for function deselections. There is a side effect that deselecting backward from a closure will now leave your cursor totally clear of the closure (ie. on the paren or comma preceding it in the function call). This doesn't feel too bad, though, and as tradeoffs go I'd rather take the whitespace skip. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This behavior is feeling right 👍
The whitespace trimming feels a little hacky - I suspect
I think in this case |
hm, is that not the behaviour you're getting? that's precisely what happened for me when I just tested it now, and what I intended to implement.. edit: oh, are you suggesting clipping the whitespace from the position goto_treesitter_object returns to get to the end of the previous block is itself a hack? that's.. probably true, it wants to go to the start of the current block, not the end of the previous one. unfortunately, I wasn't sure how to replace that |
Testing my assumptions, I collected the filtered nodes to a Vec, sorted by key, and popped the last one before returning the next last - this leaves us in the whitespace before the just-deselected function, as suspected. Popping again puts us at the top of the previous function, effectively deselecting both in one movement. There's no way around treesitter including whitespace at the end of the item either, as you'll see from the issue I linked earlier (it's suggested to simply consult the original buffer using the TS node's start and end bytes). Hence, without diving in and filtering the whitespace as we have, I'm at a loss how to achieve the desired behaviour for Helix. |
I think that's because of the direction of the range returned by |
It seems that no amount of manipulation I throw at the treesitter movement can make this work in a straightforward fashion.. actually, all I found is that we probably need to trim whitespace forward as well :) At this point, I'll step back unless the whitespace skip is deemed acceptable or some other route is found. |
I've picked this up in #3266 |
Previously, when using bracket gotos with select mode enabled, treesitter object-based options would ignore select mode completely.
This patch implements select mode behaviour consistent with paragraph bracket gotos for treesitter objects.