Vim — delete and yank lines without a single move

Oleh Baranovskyi
3 min readMay 29, 2021

--

Today I have written a vim script that helps to remove and yank lines without any moves and want to share it!

When it can be useful? — Always! There are always cases when you need to copy or remove the particular lines in the file and the faster you're doing it is better. For instance, when you refactor your code and you realize that some method, variable, import(TS, JS), include(C, C++), using(C#), etc. is not needed anymore, or need to be moved, and this is the case when the current script can become handy.

In order to use this script, you need to set the relative numbers. To do so add the following line to your vim config file:

set relativenumber

Ok, we have text that looks like this:

  5 | January - 31 days
4 | February - 28 days in a common year and 29 days in leap years
3 | March - 31 days
2 | April - 30 days
1 | May - 31 days
6 | June - 30 days
1 | July - 31 days
2 | August - 31 days
3 | September - 30 days
4 | October - 31 days
5 | November - 30 days
6 | December - 31 days

so right now we are on line 6, and we want to remove lines that contain January, February, and March to do that we can type:

-5,-3d

In order to yank the same lines, we can do the same action but instead of d we need to put y .

-5,-3y

However, we’ll lose the cursor position, and in our case, it’s not what we want. Here is the script which is going to preserve the position:

function! s:RemoveRowAndJumpBack( ... ) abort
execute "normal ma"
let isRange = get(a:, 2, 0)if isRange
execute a:3 . a:1 . ',' . a:3 . a:2 . 'd'
else
execute a:2 . a:1 . 'd'
endif
execute "normal `a"
execute "delmarks a"
endfunction
command! -nargs=+ PositiveRelativeRemoveRow call s:RemoveRowAndJumpBack(<f-args>, '+')
command! -nargs=+ NegativeRelativeRemoveRow call s:RemoveRowAndJumpBack(<f-args>, '-')
nnoremap <leader>dj :PositiveRelativeRemoveRow
nnoremap <leader>dk :NegativeRelativeRemoveRow

and for yank:

function! s:YankRowAndJumpBack( ... ) abort
execute "normal ma"
let isRange = get(a:, 2, 0)if isRange
execute a:3 . a:1 . ',' . a:3 . a:2 . 'y'
else
execute a:2 . a:1 . 'y'
endif
execute "normal `a"
execute "delmarks a"
endfunction
command! -nargs=+ PositiveRelativeYankRow call s:YankRowAndJumpBack(<f-args>, '+')
command! -nargs=+ NegativeRelativeYankRow call s:YankRowAndJumpBack(<f-args>, '-')
nnoremap <leader>cj :PositiveRelativeYankRow
nnoremap <leader>ck :NegativeRelativeYankRow

Now in order to accomplish our previous tasks, we need to click <leader>dk and enter 5 3 or to yank click <leader>ck and enter like previously 5 3 and hit the enter. In order to do that with text which is below <leader>dj and <leader>cj can be used.

With this script, you can remove and yank single lines as well. To do so you can use the same key bindings, however, instead of entering two numbers like before you need one.

You can go even further and add more similar scripts to accomplish such tasks.

Was it helpful? If so, please click the clap 👏 button below ⬇️ so more people can see this!

--

--