-
-
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
expand_selection_around
#6198
base: master
Are you sure you want to change the base?
expand_selection_around
#6198
Conversation
bdb3bbd
to
973772c
Compare
Loving the new/improved motions very useful 👍 About the object selection: I think you need to discard that when any transaction is applied too (since Thus change would also be interesting for virtual text/folds since that is yet anthor instance of view & document specific data that needs to be updated in Furthermkre for conceal/fold in particular it would actually be really neat if we centralized all selection changes into a single function so we can hook into it more easily. Perhaps that could be done here since you essentially need the same thing: clear all object_selections whenever the selection changes in any way (with a few exceptions) |
I marked this as waiting on PR for now until #6156 is merged |
973772c
to
c2ddb01
Compare
Yeah, this is true, but because of the last sentence, I figured it would be better to make a concrete improvement to the situation to start with before tackling it in the general case, since that's a much larger change.
This is a really interesting suggestion. Let me look through the code again and try to conceptualize this more concretely. |
Yeah, after looking through it again, I think you are right; this would actually be less invasive, since we wouldn't have to take a whole I'll try out this change. |
9d1b9c9
to
d296d63
Compare
Mentioned in chat, but I implemented the above suggestion, and the diff is a lot cleaner, and it covers more corner cases to boot 🎉 |
ce8c4fc
to
f79a10e
Compare
3594e43
to
f0446ae
Compare
9bbac17
to
a36459b
Compare
a36459b
to
10edb7c
Compare
10edb7c
to
1e28dfc
Compare
4325877
to
b761102
Compare
d67a9fe
to
d1c987d
Compare
d2d2472
to
4759056
Compare
4759056
to
0762a30
Compare
0762a30
to
a01c101
Compare
a01c101
to
ebb3e91
Compare
ebb3e91
to
9434010
Compare
9434010
to
f0a61d0
Compare
f0a61d0
to
0f47d17
Compare
0f47d17
to
06d4756
Compare
Ok, I've rebased this. Additionally, as was discussed in chat, I changed the behavior of In the case where there is no previous selection history from doing an
The only thing I'd like to do is write some unit tests for the recursive walker. Integration tests pass, but focused unit tests would be better. |
11b65c6
to
55071fd
Compare
55071fd
to
50cdcd3
Compare
50cdcd3
to
232a753
Compare
232a753
to
0fd32ed
Compare
0fd32ed
to
1540d91
Compare
1540d91
to
d83b4d8
Compare
d83b4d8
to
9d6e303
Compare
9d6e303
to
73b4511
Compare
73b4511
to
4e88624
Compare
Adds a method of breadth-first recursive descent for TreeCursors
This changes the behavior of `shrink_selection` to iterate through child nodes until it finds one that is contained within the selection, with at least one of the ends of the selection being exclusively inside the starting selection (though not necessarily both ends). This produces more intuitive behavior for selecting the "first logical thing" inside the selection.
Adds two helper functions to `Selection`: * `overlaps`: tests whether two `Selection`s contain any ranges which overlap with each other * `without`: Computes a new `Selection` that is the set difference of two `Selection`s, i.e. everything in the first `Selection` with everything that overlaps in the second `Selection` removed, potentially leaving holes in the original ranges. It also fixes a bug with `Selection::contains`: it assumes that if the second `Selection` has a greater number of ranges than the first, then the first cannot contain the second; but this is false, since one range from the first could contain multiple smaller ranges in the second.
This allows using multiple distinct state histories. By default, all history is also cleared any time a view's selection is set, unless explicitly told to save the state. This way, we can have control over when selection history is saved. They are also cleared on any text edit, since an edit could invalidate the previous selection, potentially causing a panic. Additionally, the object selections have been moved into `Document` so that it is easier to manipulate them when changes to the document happen. They have been put into a wrapper struct named `ViewData`, where the intention is that any further fields that we want to add in the future that must be associated with a view, but are more convenient to store in a document, can be added here, instead of further polluting the core `Document` type.
Introduces a new command `expand_selection_around` that expands the selection to the parent node, like `expand_selection`, except it splits on the selection you start with and continues expansion around this initial selection.
4e88624
to
3b177ad
Compare
This adds a new feature:
expand_selection_around
. With this command, one starts with an initial arbitrary selection, and then theexpand_selection_around
acts just likeexpand_selection
, except that it splits the new expanded selection around the initial selection. All the while, it remembers what the initial selection was so that you can continue to expand any number of times around this initial selection. Additionally, shrinking works exactly the same way, except that once you get back down to the first expansion, the last shrink in the stack will revert back to your initial selection.Implementation
The existing
expand_selection
andshrink_selection
commands are implemented by keeping a list ofSelection
s, which they push and pop off of like a stack.In order to implement this feature, these "object selections" are generalized into a register of namespaced lists of
Selection
s. Currently these are keyed by hardcoded static strings; this felt cleaner than having special struct fields. Theoretically, other commands that could make use of tracking lists ofSelection
s could use this register in the future too, without specialized members.Anyway, this particular feature is implemented by keeping 3 distinct
Selection
histories:expand
: this serves the role of the existing object selections: it remembers your final selections at each step of the way, so that you can shrink back down to your previous selectionsexpand_around_base
: this remembers your initial "base" selection before running theexpand_selection_around
commandparents
: this tracks the entire span of the parent nodes as you are traversing up the syntax treeThe feature is accomplished by essentially pretending internally that we only have one selection: the entire span of a parent node. Each time we
expand_selection_around
again, this parent node is used to keep traveling up the tree. But before we actually set the final resulting selection, we take theexpand_around_base
selection and split the parent span into two around the base.For this, it was necessary to add
Selection:: without
, which computes the set difference of twoSelection
s.Incidentally, along the way, I discovered the same bug reported in #6092, so this includes the same fix as, and could possibly supersede, #6093.
Additionally, I also noticed all the bugs that @pascalkuthe mentioned in #6088 (review) and #6087, i.e. the current object selections don't track all the context that they should: they can end up getting used on the wrong document, view, and could end up getting totally out of sync with any text edits that happen between an expansion and a shrink.
As @pascalkuthe mentioned, fixing this in the general case would be somewhat complex, as it would need to track any text edits and possibly associate views with selection histories, as mentioned in #6088 (comment). How this would ultimately end up interacting with the changes in this PR are unclear.
But in any case, I addressed these issues in a simple, but very aggressive way: the object selections are now cleared any time a view's selection is set, except during these expand and shrink commands. This required a breaking change in
Document::set_selection
: it has to take a mutable reference to the entireView
now in order to clear the object selections. This is a simple way to ensure that the object selections don't get out of sync with view switches or document edits, since it's likely that every command that could cause a problematic divergence in the object selections also itself sets a selection, plus many that wouldn't. This includes normal mode movements of any kind, for example.Consequences of this include:
Also, this PR changes the behavior of
shrink_selection
when there was no previous expansion. Currently, the first child is selected. However, this is often not very useful at all, since the first child often something like an open brace or parentheses. Instead, the behavior is changed to select the first child that is strictly contained within the span of the current node (credit and thanks to @pascalkuthe again for this idea!). The command is much more useful this way.@matoous may be interested in this PR as it builds upon their original implementation of the expand and shrink commands.
Based on top of #6156 since it makes use of some of the integration testing improvements
Fixes #6092
Supersedes #6093
Fixes #6087