Search code examples
vimneovim

Yanking /moving a selection of text in vim


<template>
   <h1>Hello</h1>
</template>

If I search this using

/<template>\_.*template>

How do I yank/cut the selection to put it somewhere else in the file?

Is there a better way to go about doing this?


Solution

  • The thing is that, after a search, you have a match, not a selection. If you want to do something with that match, you must turn that match into either a motion, a selection, or a range. The versatile :help gn can help with all three.

    Match to Motion

    Once the search is done, you can do:

    dgn
    

    to cut the matched text and then move the cursor elsewhere and press p or P to put it there. The problem with this is that the register is character-wise, so your snippet might be inserted in the middle of a line, which is not good. You can also do something like:

    :/foo/put=@"
    

    or:

    :6put=@"
    

    which will put the text in a line-wise way because Ex commands like :put are all line-wise.

    See :help gn, :help :range, and :help :put.

    Match to selection

    Alternatively, you can select the matched text in visual-line mode:

    Vgn
    

    and cut it with d. Since this was done in visual-line mode, the register is line-wise so you can put your snippet with p/P anywhere without too much risk.

    With the methods above, you kind of decide what you do as you do it, one atomic action after another. Go there. Take this. Go there. Do that.

    A different approach

    This is absolutely fine but, over the years, I have come to appreciate the higher level of expressiveness of Ex commands a whole lot more for scenarios like this.

    Here is how I would have done it ("move text after last line", here):

    :/<template/,/<\/template>/m$
    

    See :help :move.

    Match to range

    And here is another one, that mixes all of the methods/approaches above plus one:

    /<template>\_.*template><CR> 
    vgn
    :'<,'>m$
    

    Where…

    • you make a match,
    • you turn it into a selection by treating it as a motion
    • and you finally use it as range.

    Everything

    FWIW, here are all of the above methods displayed in a concise way:

    /<template>\_.*template><CR>
    dgn
    <motion>
    p
    

    /<template>\_.*template><CR>
    dgn
    <motion>
    :<address>put=@"
    

    /<template>\_.*template><CR>
    Vgn
    d
    <motion>
    p
    

    :/<template/,/<\/template>/m$
    

    /<template>\_.*template><CR> 
    vgn
    :'<,'>m$