1
votes

I know how to delete blank lines with commands.

We may visually select the text block first, and then run commands like s/^$/d to delete all blank lines or %s/^\(\s*\n\)\+/\r to keep only one blank lines.

Can I perform the above using motion, so that I can just press some keys to perform the "delete-motion" without having to enter command-line mode?

4
Well, you can make a key mapping to that ex-command.doubleDown
d/^. will delete from here until the next non-blank line, or if you've already done that search before, then simply dn, but "here" needs to be a sensible value. Will that do?sh1
@sh1, Thank you! Then for deleting backwards d/.$! Probably I would have not asked this question if I knew d/^.. :)ying17zi
@Hongying, unfortunately the reverse pattern seems to eat the last character of the non-empty line. I thought it would be d?^\@!$, but no such luck.sh1

4 Answers

3
votes

Creating a new operator for this is a good idea, but it can be tough to get right.

The operator-user plugin makes that task easy.

Once you have installed operator-user, all you need to do is add two lines to your vimrc, one to define the operator, and one to define your personal mapping to it:

call operator#user#define_ex_command('delete-blanks', 'g/^$/d')
map _ <Plug>(operator-delete-blanks)

This creates a new operator _. Change it to whatever you like best.

Now you can do _3} or _G or _23k to delete the blank lines contained in the motion. Text objects _a}, doubling of the operator 4__, and Visual mode V7j_ are all also supported, as befits a proper operator.

2
votes

You could use operatorfunc. For example:

Define a function like this in your .vimrc:

function! DeleteEmptyLines(type)
    if a:type == 'line'
        silent execute ".,'\"g/^$/d"
    endif
endfunction

And a mapping:

nnoremap <silent> ,d :set operatorfunc=DeleteEmptyLines<CR>m"g@

,d performs now just like an operator and accepts a (line-based) motion. You can, for example, insert ,d5j or ,dG in normal mode to delete empty lines in the next 5 lines or to the end of file.

You can find more information on how to extend this functionality here: http://learnvimscriptthehardway.stevelosh.com/chapters/33.html and of course::h operatorfunc and :h map-operator.

From :h map-operator:

"An operator is used before a {motion} command. To define your own operator you must create mapping that first sets the operatorfunc option and then invoke the g@ operator. After the user types the {motion} command the specified function will be called."

1
votes

well, using motions I don't think you can only delete blank lines.

But you can do it using a mapping:

:nmap <Leader>db :g/^$/d<CR>

The motions help you move one word, one paragraph away... And before the motion you use an operator (d, c...).

So what you'd want is to create a new operator that deletes blank lines within the given motion (or selection). What I gave you is close to that, but you'd have to invent a new operator (and I don't think there's many unbound keys left).

Other vimmers may correct me, but I think the easiest way to create such operators would be to define a map for each motion and bind it to a function.

-1
votes

There isn't a motion that can combine with a delete such that it only deletes blank lines. A motion denotes all the text between the initial and final position, without any gaps. That includes motions which search using regular expressions.