-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
vim: Add exchange #24678
vim: Add exchange #24678
Conversation
@ConradIrwin Thanks for the pairing sesh earlier. I added some docs and some inital tests for this -- at least as far as I've seen tests in other PRs here. It might not be the right place or way of writing it, so please let me know if they should go somewhere else. Two of the tests deal with the overlap logic which isn't currently implemented. I took a stab at it, but couldn't find the way to compare ranges for overlaps because Anchor doesn't impl PartialOrd. There's probably something obvious I'm missing though. If you can give me some pointers, I'd be happy to take another crack at it, but if you think it'll be faster/easier adding it yourself, that's totally fine too. |
@thomasheartman you have two choices, if you have a buffer snapshot you can do If you don't get to it, I'll pick this up in a few days. |
Thanks! I think I've got it working as intended now (as far as I can tell). I've moved the tests into the same source file, and they run just fine. One thing though, that I .. might like to resolve: In evil exchange, you end up with the cursor at the beginning of the last selected object, whereas in Zed, you're currently at the end. Is there a function to "go to point in buffer" or something like that? I tried looking at the editor struct, but couldn't find a specific "go to X" function? In other words, the first test currently expects this:
But I'd actually expect this:
|
@thomasheartman nice! Selections are a bit fussy (because in general you might want to have many). Probably the right thing to do in this case is to store the anchor at the start of the range, and then select it. If you're lucky you may be able to re-use the helpers from the indent code: Lines 24 to 29 in a7a42b3
But if you need something slightly different, feel free to copy and modify. |
Thanks! I'll have a look later 🙋🏼 Been out of commission for a couple of days due to a back injury, but I'm at least doing well enough to sit in a chair now 😅 I'll let you know if I can't figure it out 🙌🏼 |
@ConradIrwin Thanks for again for the pointers! I went digging a bit and found With that out of the way, I believe this PR is ready to go, so feel free to have a look and let me know if you want any changes (or feel free to make them yourself). |
I've also added a release notes section to the PR description using the format that the bot suggested. Again, feel free to lemme know or edit yourself if the format isn't correct. |
@ConradIrwin Sorry for the ping, but just so that this doesn't go too stale: is there anything I need to / can do to move this forward? Any remaining work you'd like to see? The one thing I can think of is what to do in visual mode, where shift-x is already bound to delete line. I don't think there's a different canonical shortcut for exchange in that setting, so might be best to just take it out and make a note of it in the docs? Happy to do that, if so. |
No worries, sorry for putting this on the back burner. Happy to ship without the visual mode keybinding conflict. |
No worries at all! I removed the keybinding and added a note for it under the optional keybindings section (and added a note about it higher up. |
Implements vim-exchange functionality.
Lets you swap the content of one selection/object/motion with another.
The default key bindings are the same as in exchange:
cx
to begin the exchange in normal mode. Visual mode does not have a default binding due to conflicts.cxx
selects the current linecxc
clears the selection.
will repeat that operation.Closes #22759
Overlapping regions
According to the vim exchange readme:
Zed does the following:
Not implemented: cross-window exchange
Emacs's evil-exchange allows you to exchange across buffers. There is no code to accommodate that in this PR. Personally, it'd never occurred to me before working on this and I've never needed it. As such, I'll leave that implementation for whomever needs it.
As an upside; this allows you to have concurrent exchange states per buffer, which may come in handy.
Bonus
Also adds "replace with register" for the full line with
grr
🐕 This was an oversight from a previous PR.Release notes:
vim-exchange
Vim::CurrentLine
for replace with register mode (grr
)