-
Notifications
You must be signed in to change notification settings - Fork 190
Vi mode text objects for word, WORD, brackets and quotes #939
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
Vi mode text objects for word, WORD, brackets and quotes #939
Conversation
…tespace Note a buffer full of whitespace is not properly considered and still causing incorrect behaviour. TODO fix this.
…add general yank/cut range methods
…eatures - Now handles jumps to next open/close or equal symbol pairs if not in a pair already - Searching only on current line for equal symbol pairs e.g. quotes - Correctly handles graphemes
- Refactor the structure of the methods to get ranges, don't need to pass in depth unecessarily, high level functions don't require cursor passed in. - Now two seperate functions for ranges, one "next" and one "current" range that gets you either the range inside next text object or inside current one depending on position of cursor. - Finilise logic to correctly handle graphemes (not byte sized chars) TODO Update unit tests
- Improve some text object ranges to use iterators rather than complex logic - Clean up documentation, add consts etc - Look through and refactor some editor functions
… and rewrite a lot of doc strings
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.
I have been wanting this for a while. This much better than the hack a while back.
The code looks clean and seems to work fine in nushell (minus a couple minor changes).
Great work!
@ayax79 Glad to help! These motions are so hard coded into my brain it felt clunky trying to edit without them haha. |
EditCommand::CopyInsidePair { .. } => EditType::EditText, | ||
EditCommand::CutAroundPair { .. } => EditType::EditText, | ||
EditCommand::CopyAroundPair { .. } => EditType::EditText, |
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.
I believe the EditType for Copy command should be a noop.
EditCommand::CopyInsidePair { .. } => EditType::EditText, | |
EditCommand::CutAroundPair { .. } => EditType::EditText, | |
EditCommand::CopyAroundPair { .. } => EditType::EditText, | |
EditCommand::CopyInsidePair { .. } => EditType::NoOp, | |
EditCommand::CutAroundPair { .. } => EditType::EditText, | |
EditCommand::CopyAroundPair { .. } => EditType::NoOp, |
Let's move forward with this. Thanks! |
@JonLD would you mind looking at this PR nushell/nushell#16791. I left out https://github.com/nushell/reedline/pull/939/files#diff-2dbf826b03a6d3f8d1d1e31324494945d307b79a9592d7eddf70f1d9bdfd1473R408-R416 because i wasn't sure how to implement them with TextObject in nushell. |
Thanks for getting this merged! As mentioned on the MR, I believe the text object types need to be publicly exposed so the correct EditCommand can be called. |
This PR updates nushell to the latest reedline commit 32e82c27. Notes from @JonLD regarding reedline's new `TextObject`, reedline change author of nushell/reedline#939 and nushell/reedline#957 and #16808 Since EditCommand contains a TextObject and not a string it is not possible for the user to directly there needs to be a bit of work done to construct the relevant text object. Maintains the edit command names, seen under "keybindings list", of CutTextObject and CopyTextObject and using scope: <inner|around> and the object_type: mirrors the Reedline implementation and the informative error messages should help signal to users what are valid inputs. Ideally the "keybindings list" would be a bit mor informative as to how to set up specific keybindings but that's not currently possible, and perhaps not even necessary. The alternative would be to set up edit commands for each text object, this would be a larger Reedline change and add unecessary complexity to Reedline but would expose the commands better to the use. You could just add them in this file and keep Reedline as is but that would not be exposed to the user via "keybindings list" as this command lists the actual enums and not commands set up in the reedline_config.rs. ## Release notes summary - What our users need to know Breaking change since the reedline change renames `cutinside` and `yankinside`. The PR adds these new EditCommands: - cutinsidepair - copyinsidepair - cutaroundpair - copyaroundpair - cuttextobject - copytextobject ## Tasks after submitting N/A
Overview
Implements the vim style inner and around (
i
anda
) text objects for:w
(a sequence of letters, digits and underscores, separated with white space)W
(a sequence of non-blank characters, separated with white space)b
(any of( )
,[ ]
,{ }
)q
(any of" "
,' '
,``
)di(
orci"
) extended for around versions that cover the pair charactersThis addresses most of #848 although it doesn't add paragraph text object, that would be fairly straightforward to add later.
Additionally, the pair motions will now jump to the next pair if non are found within search range. For symmetric pairs like quotes searching is restricted to the current line. For asymmetric pairs like brackets search is multi-line across the whole buffer. Symmetric pairs searching does not do any parsing or matching of pairs based on language/groupings. It simply searches for the previous and next matching characters (this is consistently with vim but could be improved, perhaps using tree sitter).
Repeats
While it might not be the intend to achieve identical behaviour as vim I thought it useful to compare to the default vim behaviour of repeats.
Around brackets:
In the current implementation repeat motions for
around
text objects will cause a jump to the next bracket.e.g. 2daw on "(first)between(second)" while in the first bracket will delete both the first and second bracket, included the parentheses themselves, and move the cursor to the end "between".
Vim works around this by not letting you do repeats for "around" motions unless inside a nested bracket.
Inner words:
Repeat motions for words also differ from default vim behaviour for repeated word text objects. In vim a
2diw
performs a single around diw command and then the repeat command isdw
. The difference in behaviour is that in the reedline implementation2daw
ondelete th|is word
will result indelete|word
whereas in vim it would bedelete |word
.This could perhaps be worked around by adding a method of passing an alternate command for repeats to the command module which could be made in a future change. I think the current behaviour is satisfactory for most use cases.
Word identification
Currently due to using the unicode-segmentation crate for splitting at word word boundaries word does not have the same meaning as Vi/Vim. This means
diw
onnot.a..wo|rd
will delete the whole WORD rather than just the word under the cursor.