Vim Tips Wiki
Advertisement

Previous TipNext Tip

Tip: #1066 - Quickly adding and deleting empty lines

Created: December 4, 2005 5:46 Complexity: basic Author: Ulfalizer Version: 6.0 Karma: 17/19 Imported from: Tip#1066

When programming, I often find myself adding and deleting empty lines. The way I used to do it was to press o (or O) to open a new line, press Enter if I wanted additional lines, and then press ESC to exit insert mode. Often I wanted to find my way back to where I began the insertion, and so had to do a few kkk, jjj:s (this was before I discovered the '[ and '] motions). This was getting cumbersome, and so I came up with another mechanism.


The following remaps C-j to add empty lines below the cursor and C-k to remove empty lines below the cursor (you'll find these are intuitive "up/down" operations). A-k and A-j do the same thing above the cursor. Lines containing something other than whitespace are not deleted, and so the delete operations can be "hammered on" without risk. The cursor maintains its position in the window if possible. You should probably set scrolloffset to something other than 0 for optimum comfort.


function! AddEmptyLineBelow()

call append(line("."), "") 

endfunction


function! AddEmptyLineAbove()

let l:scrolloffsave = &scrolloff 
" Avoid jerky scrolling with ^E at top 
" of window 
set scrolloff=0 
call append(line(".") - 1, "") 
if winline() != winheight(0) 
silent normal! ^E 
end 
let &scrolloff = l:scrolloffsave 

endfunction


function! DelEmptyLineBelow()

if line(".") == line("$") 
return 
end 
let l:line = getline(line(".") + 1) 
if l:line =~ '^\s*$' 
let l:colsave = col(".") 
.+1d 
 
call cursor(line("."), l:colsave) 
end 

endfunction


function! DelEmptyLineAbove()

if line(".") == 1 
return 
end 
let l:line = getline(line(".") - 1) 
if l:line =~ '^\s*$' 
let l:colsave = col(".") 
.-1d 
silent normal! ^Y 
call cursor(line("."), l:colsave) 
end 

endfunction


noremap <silent> <C-j> :call AddEmptyLineBelow()<CR>

noremap <silent> <C-k> :call DelEmptyLineBelow()<CR>

noremap <silent> <A-j> :call DelEmptyLineAbove()<CR>

noremap <silent> <A-k> :call AddEmptyLineAbove()<CR>



Note that ^E and ^Y should be the real things and not entered with ^ and E/Y as separate cahracters. Press C-V C-E, C-V C-Y to insert them.

Comments

If you don't mind the safety error messages, you can do this without any functions:

noremap <silent><C-j> mzo<Esc>`z noremap <silent><C-k> mz:+g/^$/d<CR>`z noremap <silent><A-j> mz:-g/^$/d<CR>`z noremap <silent><A-k> mzO<Esc>`z

Gerald Lai , December 4, 2005 15:14


The error messages can be avoided by prepending :silent, noremap <silent><C-j> mzo<Esc>`z noremap <silent><C-k> mz:silent +g/^$/d<CR>`z noremap <silent><A-j> mz:silent -g/^$/d<CR>`z noremap <silent><A-k> mzO<Esc>`z

I had no idea Vim remembered column positions for marks. That's pretty handy.

One drawback (which might also be considered a feature) with these bindings is that using C-j when the cursor is on i.e. a C++ // comment will make Vim insert another // on the next line, which unfortunately C-k will then not be able to delete.

Another drawback is that A-j and A-k will not preserve the cursor's position in the window.

Anonymous , December 4, 2005 16:57


The following version deletes lines containing only whitespace as well, but has the same minor problems,

noremap <silent><C-j> mzo<Esc>`z noremap <silent><C-k> mz:silent +g/\m^\s*$/d<CR>`z noremap <silent><A-j> mz:silent -g/\m^\s*$/d<CR>`z noremap <silent><A-k> mzO<Esc>`z

\m turns on the 'magic' option for the rest of the pattern so that it will work regardless of what the user has set 'magic' to.

Ulfalizer , December 4, 2005 17:16


The mappings provided only maintain the cursor position in the buffer. To maintain the cursor position in the window, do this slight modification:

noremap <silent><A-k> mzO<Esc><C-e>`z 

It's hard to maintain the cursor position in the window for <A-j> due to the inherent deletion of the line before the current one.

I was unable to replicate the "<C-j> when cursor is on a C++ // comment" behavior.


Gerald Lai , December 4, 2005 17:46


To avoid the "comment" anomaly you can use the following mappings:

noremap <silent><C-j> :set paste<CR>mzo<Esc>`z:set nopaste<CR> noremap <silent><A-k> :set paste<CR>mzO<Esc>`z:set nopaste<CR>

(I thought I would never find a use for the 'paste' option ;-)

Also if you use the hlsearch option you'll probably want the following to hide the highlight of empty lines:

noremap <silent><C-k> mz:silent +g/\m^\s*$/d<CR>`z:noh<CR> noremap <silent><A-j> mz:silent -g/\m^\s*$/d<CR>`z:noh<CR>

Regards. Rodrigo.

rodrigorivascosta at gmail.com , December 5, 2005 0:29


I get no visible highlighting of empty lines. When is highlighted empty lines a problem?

Ulfalizer , December 5, 2005 4:33


The 'g' command sets the last search pattern, so I get the empty lines highlighted. Naturally, I have the 'hlsearch' option on.

Rodrigo.


rodrigorivascosta at gmail.com , December 6, 2005 5:47


It's simple to find where you start before insertion.

o enter blah blah blah ENTER blah ENTER (input stuff) ESC u ^R

Now you're in original position. Nothing special required.

Anonymous , December 8, 2005 19:42


It's still a hassle to have to press 'o', then enter (if you want many empty lines), then esc, then u, then ^R for every empty line to want to add to a file.

Anonymous , December 13, 2005 4:29


I did it like this:

nnoremap <c-j> o^[

(Press <c-v> and ESC to get o^[ )

janne , April 10, 2006 4:14


Advertisement