zed
zed copied to clipboard
Vim mode surrounds
Check for existing issues
- [X] Completed
Describe the feature
A very common Vim plugin is vim-surround by the infamous tpope, and the nvim lua rewrite nvim-surround. These keybinds are muscle memory for me and are the first thing I install when setting up a vimmish editor.
VSCodeVim has these keybinds built in.
I don't think I need to specify any more than this because I can't think of anyone that doesn't use this, but for the sake of keeping the issue self contained:
-
ys[motion][char]
will surround the motion or textobj with char- If char is an opening bracket/paren, it will pair it with the close bracket and insert a space on both sides for padding eg. with the text
|word
, the commandysaw{
transforms it to become{ word }
- If char is a closing bracket, the same as above happens but no spaces are inserted.
- If char is an opening bracket/paren, it will pair it with the close bracket and insert a space on both sides for padding eg. with the text
-
ds[char]
deletes the surrounding characters, or if char is a paired character it deletes the pair. -
cs[old][new]
changes the surrounding characters from old to new- The same rules about opening/closing pairs apply w.r.t inserting a space or not.
The vim-surround readme has a better explanation of all of this of course!
If applicable, add mockups / screenshots to help present your vision of the feature
No response
this is useful outside of vim too
I'll add a general example so people can reason easily about it:
Imagine the following example:
<strong>This text should be italic</strong>
While i'm within strong
context I want to be able to select the surrounding pairs, and replace them with <i>context</i>
.
<i>This text should be italic</i>
Here's the implementation for helix editor.
This feature is really needed
This feature is so important to me, it will take me one step further to mainly use zed❤️
If possible, I'd be willing to submit a project to try to provide this functionality
Just adding a note for any future implementers/contributors - make sure this works with non-bracket characters too! I sometimes want to surround a word/selection with `, *
, ~
,
, and more. I've seen a lot of implementations of surrounds that don't work with other characters
Just adding a note for any future implementers/contributors - make sure this works with non-bracket characters too! I sometimes want to surround a word/selection with
,
*,
~,
`, and more. I've seen a lot of implementations of surrounds that don't work with other characters
Can you give an example of the last two characters, just curious
I think the last two characters are backtick and tilde:
\``, *, ~, `
@weartist some more examples
viwS"
-
v
visual -
i
inner -
w
word -
S
surround selection with -
"
"
Can be used with anything visual so the important part is S<something>
Examples:
-
viwS"
:this is the t<cursor>ext
becomesthis is the "text"
-
VS"
:
becomesthis is a <cursor>sentence
" this is a sentence "
-
0v$S(
:
becomesthis is a <cursor>sentence
(this is a sentence)
This is definitely a must have for me as well! Awesome editor, if this feature lands zed will definitely be a daily driver for me.
Literally waiting on this for zed to be my daily driver. Everything else i use and see are great so far, but gotta have surround.
I have write a simplified version with only add surround. I will add modification and deletion operations as soon as possible and then provide PR
+1. I'm struggling with not having this in an otherwise stellar editor.
+1, only thing holding me back from zed is a fully featured vim-mode
@weartist Still planning on opening a PR? Do you have a partial implementation you can share?
@weartist Still planning on opening a PR? Do you have a partial implementation you can share?
I'm sorry I didn't have much time in the past two weeks, I'll continue this PR next week if I can
Ok, if you don't have enough time or motivation to complete it don't hesitate to open even a partial PR, others can chime in.
Are we ok to close this issue out now that v0.131.0-pre supports this?
I think we should close this, and (probably) open a follow-up for HTML tag support.
@ConradIrwin doesn't support yss
I think for yss
(and css
) we can start with something like:
{
"context": "Editor && (vim_operator == ys || vim_operator == cs)",
"bindings": {
"s": "vim::CurrentLine"
}
},
Unfortunately this includes the trailing newline which we don't want to, so will need some code changes too.
Is it too late for a feature request? A shortcut for surrounding the closest pair of things: https://github.com/VSCodeVim/Vim/issues/8699
Not too late! Probably best as a separate issue, or if you'd like to pair on it together: https://calendly.com/conradirwin/pairing
Is there a solution for S
being occupied? Visual surround - viwS
doesn't work, because S
deletes a line and enters insert mode.
Not currently. I think we'd have to build an action for surround in visual mode and then show an example in the docs of how to map S
to that in visual mode.
If you'd like to work on this with me: https://calendly.com/conradirwin/pairing
Is there a solution for
S
being occupied? Visual surround -viwS
doesn't work, becauseS
deletes a line and enters insert mode.
I thought I had commented this a few weeks ago.. but it's pretty easy to simulate this through custom key binds, although you'll have to hardcode every surround character type. And S
still retains its default functionality, although there's a delay in visual mode as it looks for a keybind chord.
Note about my comments: I think the vim paste is only needed because I have the copy on yank only setting enabled. If you don't have that enabled, any of these surround commands will pave over your system clipboard. And you would just replace the custom vim paste shortcut with your key bind for normal paste (although vim paste should still work), and you might have to mess with the left
arrows to make sure everything is in the right spot.
{
//vim visual mode
"context": "Editor && vim_mode == visual && !VimWaiting && !VimObject",
"bindings": {
"s": "editor::SelectSmallerSyntaxNode",
";": "editor::SelectLargerSyntaxNode",
// shift-s binds (Surround) rely on custom keybinding (ctrl-g p) for vim paste
"shift-s '": ["workspace::SendKeystrokes", "d i ' ' left left ctrl-g p"],
"shift-s `": ["workspace::SendKeystrokes", "d i ` ` left left ctrl-g p"],
"shift-s \"": [
"workspace::SendKeystrokes",
"d i \" \" left left ctrl-g p"
],
"shift-s [": [
"workspace::SendKeystrokes",
"d i [ space space ] left left left ctrl-g p"
],
"shift-s ]": ["workspace::SendKeystrokes", "d i [ ] left left ctrl-g p"],
"shift-s {": [
"workspace::SendKeystrokes",
"d i { space space } left left left ctrl-g p"
],
"shift-s }": ["workspace::SendKeystrokes", "d i { } left left ctrl-g p"],
"shift-s (": [
"workspace::SendKeystrokes",
"d i ( space space ) left left left ctrl-g p"
],
"shift-s )": ["workspace::SendKeystrokes", "d i ( ) left left ctrl-g p"]
}
},
{
//vim insert mode
"context": "Editor && vim_mode == insert",
"bindings": {
"ctrl-g p": "vim::Paste" //Uses the vim clipboard
}
}
For anything you don't happen to have hardcoded, you could just do a cs
command (e.g. cs'*
to change quotes to asterisks) after doing one of your hardcodes