zed icon indicating copy to clipboard operation
zed copied to clipboard

Vim mode surrounds

Open clo4 opened this issue 1 year ago • 14 comments

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 command ysaw{ transforms it to become { word }
    • If char is a closing bracket, the same as above happens but no spaces are inserted.
  • 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

clo4 avatar Mar 12 '23 03:03 clo4

this is useful outside of vim too

EdAyers avatar Mar 16 '23 08:03 EdAyers

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.

122865801-97073180-d344-11eb-8142-8f43809982c6

cmnstmntmn avatar Jul 26 '23 22:07 cmnstmntmn

This feature is really needed

mirageN1349 avatar Jan 25 '24 23:01 mirageN1349

This feature is so important to me, it will take me one step further to mainly use zed❤️

d1y avatar Jan 26 '24 02:01 d1y

If possible, I'd be willing to submit a project to try to provide this functionality

weartist avatar Jan 27 '24 08:01 weartist

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

clo4 avatar Jan 31 '24 05:01 clo4

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

weartist avatar Jan 31 '24 06:01 weartist

I think the last two characters are backtick and tilde:

\``, *, ~, `

mrnugget avatar Jan 31 '24 07:01 mrnugget

@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 becomes this is the "text"
  • VS":
    this is a <cursor>sentence
    
    becomes
    "
    this is a sentence
    "
    
  • 0v$S(:
    this is a <cursor>sentence
    
    becomes
    (this is a sentence)
    

alber70g avatar Feb 06 '24 14:02 alber70g

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.

instantaphex avatar Feb 16 '24 16:02 instantaphex

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.

isiktantanis avatar Feb 17 '24 15:02 isiktantanis

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

weartist avatar Feb 17 '24 16:02 weartist

+1. I'm struggling with not having this in an otherwise stellar editor.

mmtftr avatar Feb 21 '24 12:02 mmtftr

+1, only thing holding me back from zed is a fully featured vim-mode

jacksonSingleton avatar Feb 28 '24 18:02 jacksonSingleton

@weartist Still planning on opening a PR? Do you have a partial implementation you can share?

romgrk avatar Mar 08 '24 22:03 romgrk

@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

weartist avatar Mar 09 '24 08:03 weartist

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.

romgrk avatar Mar 09 '24 15:03 romgrk

Are we ok to close this issue out now that v0.131.0-pre supports this?

JosephTLyons avatar Apr 10 '24 20:04 JosephTLyons

I think we should close this, and (probably) open a follow-up for HTML tag support.

ConradIrwin avatar Apr 10 '24 21:04 ConradIrwin

@ConradIrwin doesn't support yss

0x2CA avatar Apr 11 '24 04:04 0x2CA

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.

ConradIrwin avatar Apr 11 '24 16:04 ConradIrwin

Is it too late for a feature request? A shortcut for surrounding the closest pair of things: https://github.com/VSCodeVim/Vim/issues/8699

chenglou avatar Apr 12 '24 08:04 chenglou

Not too late! Probably best as a separate issue, or if you'd like to pair on it together: https://calendly.com/conradirwin/pairing

ConradIrwin avatar Apr 12 '24 14:04 ConradIrwin

Is there a solution for S being occupied? Visual surround - viwS doesn't work, because S deletes a line and enters insert mode.

bwillem avatar Apr 25 '24 21:04 bwillem

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

ConradIrwin avatar Apr 26 '24 01:04 ConradIrwin

Is there a solution for S being occupied? Visual surround - viwS doesn't work, because S 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

quarkw avatar May 08 '24 23:05 quarkw