3

Say I have a text like

...

def my_function() do
...
end

...

And I want to yank/copy from def to end (including both def and end), so I can paste this block of text elsewhere.

Is it possible to that in vim? If so, how would I go about it?

I know that with the command yt[character] you can copy everything until the character is found, but in this case, I need to copy until end is found.

Also, it would be nice to be able to a regex to specify when to stop copying.

3

You can use a search with / or ? as a motion for a y operation. But that can be tricky, because the search motion will be characterwise and exclusive.

So if you position your cursor at the d in def and then use y/end<Return> (where <Return> means pressing the Return or Enter key), Vim will copy everything until the beginning of end except for the word end itself.

One way you can fix this is by using a /e modifier on the search, which will position the cursor at the end of the match and serve to include the word, so using y/end/e<Return> works here. You end up yanking what you originally wanted, but the yank is still characterwise, meaning it won't include a newline at the end, and if you put it at the middle of a line, it will start putting it right at the cursor position, not before or after the line. (See :help search-offset for more details on the /e modifier.)

If you want to yank the block linewise, then you can use V as a modifier to the operation. This will turn the motion from characterwise to linewise. In that case, you no longer need the /e modifier, since it's using the motion to find the last line and not necessarily the character or column in that line to end the block. Using a linewise modifier also means you can be anywhere on the initial line and it will include the whole line. To use the V modifier, simply use yV/end<Return>. (See :help o_V for more details on using V as an operator modifier.)

2
  • 1
    This is a wonderful answer, very complete. By pure chance I've stumbled upon y/end/0, I believe it would have the same effect of using V modifier, right?
    – Quasímodo
    Feb 10 at 18:02
  • 2
    @Quasímodo Yes, because adding an /{offset} at the end makes the motion linewise! :help search-commands documents that. It turns out that using /e is a little different from that, it doesn't make it linewise, but inclusive, :help search-offset documents that part... I really like o_V in that it's universal and can be applied to essentially any motion! (also o_v which can turn a motion into characterwise or change it from inclusive to exclusive or vice-versa if already characterwise.)
    – filbranden
    Feb 10 at 18:20
0

Another option that is automatically linewise and only requires your cursor be somewhere in the block is

:?def?;/end/yank

Which reads « yank from the previous line containing def to the line following that containing end ».

A comma , instead of semicolon; will also work inside the block. However, if you are outside the block, a semicolon is more effective (since it makes the next part of the range relative to the start). In the outside case, you just have to adjust the def part to get you to the def. That could be via line number, relative offset, or forward or backward search, or even a mark.

Note that, like the other answer, if there’s an end in the block before the one you want, this won’t work. In that case, it may be better to get matchpairs working and use

[go to def]yV%

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.