How can I trim blank lines at the end of file in Vim?
Sometimes I accidentally leave blank lines at the end of the file I am editing.
How can I trim them on saving in Vim?Update
Thanks guys, all solutions seem to work.
Unfortunately, they all reset current cursor position, so I wrote the following function.function TrimEndLines()
let save_cursor = getpos(".")
silent! %s#\($\n\s*\)\+\%$##
call setpos('.', save_cursor)
endfu开发者_StackOverflow中文版nction
autocmd BufWritePre *.py call TrimEndLines()
This substitute command should do it:
:%s#\($\n\s*\)\+\%$##
Note that this removes all trailing lines that contain only whitespace. To remove only truly "empty" lines, remove the \s*
from the above command.
EDIT
Explanation:
\(
..... Start a match group$\n
... Match a new line (end-of-line character followed by a carriage return).\s*
... Allow any amount of whitespace on this new line\)
..... End the match group\+
..... Allow any number of occurrences of this group (one or more).\%$
... Match the end of the file
Thus the regex matches any number of adjacent lines containing only whitespace, terminated only by the end of the file. The substitute command then replaces the match with a null string.
1. An elegant solution can be based on the :vglobal
command
(or, which is the same thing, on the :global
with !
modifier):
:v/\_s*\S/d
This command executes :delete
on every line that does not have
non-whitespace characters in it, as well as after it in the remaining
text to the end of buffer (see :help /\s
, :help /\S
, and :help /\_
to understand the pattern). Hence, the command removes the tailing
blank lines.
To delete the empty lines in a strict sense—as opposed to blank ones
containing only whitespace—change the pattern in that :vglobal
command as follows.
:v/\n*./d
2. On huge sparse files containing large blocks of consecutive
whitespace characters (starting from about hundreds of kilobytes of
whitespace) the above commands might have unacceptable performance.
If that is the case, the same elegant idea can be used to transform
that :vglobal
commands into much faster (but perhaps less
elegantly-looking) :delete
commands with pattern-defined ranges.
For blank lines:
:0;/^\%(\_s*\S\)\@!/,$d
For empty lines:
:0;/^\%(\n*.\)\@!/,$d
The essence of both commands is the same; namely, removing the lines belonging to the specified ranges, which are defined according to the following three steps:
Move the cursor to the first line of the buffer before interpreting the rest of the range (
0;
—see:help :;
). The difference between0
and1
line numbers is that the former allows a match at the first line, when there is a search pattern used to define the ending line of the range.Search for a line where the pattern describing a non-tailing blank line (
\_s*\S
or\n*.
) does not match (negation is due to the\@!
atom—see:help /\@!
). Set the starting line of the range to that line.Set the ending line of the range to the last line of the buffer (
,$
—see:help :$
).
3. To run any of the above commands on saving, trigger it using
an autocommand to be fired on the BufWrite
event (or its synonym,
BufWritePre
).
You can put this into your vimrc
au BufWritePre *.txt $put _ | $;?\(^\s*$\)\@!?+1,$d
(replace *.txt
with whatever globbing pattern you want)
Detail:
BufWritePre
is the event before writing a buffer to a file.$put _
appends a blank line at file end (from the always-empty register)|
chains Ex commands$;?\(^\s*$\)\@!?
goes to end of file ($
) then (;
) looks up backwards (?…?
) for the first line which is not entirely blank (\(^\s*$\)\@!
), also see:help /\@!
for negative assertions in vim searches.×××+1,$
forms a range from line ×××+1 till the last lined
deletes the line range.
Inspired by solution from @Prince Goulash, add the following to your ~/.vimrc
to remove trailing blank lines for every save for Ruby and Python files:
autocmd FileType ruby,python autocmd BufWritePre <buffer> :%s/\($\n\s*\)\+\%$//e
I found the previous answers using substitute caused trouble when operating on very large files and polluted my registers. Here's a function I came up with which performs better for me, and avoids polluting registers:
" Strip trailing empty newlines
function TrimTrailingLines()
let lastLine = line('$')
let lastNonblankLine = prevnonblank(lastLine)
if lastLine > 0 && lastNonblankLine != lastLine
silent! execute lastNonblankLine + 1 . ',$delete _'
endif
endfunction
autocmd BufWritePre <buffer> call TrimTrailingLines()
I have a separated function called Preserve which I can call from other functions, It makes easy to use Preserve to do other stuff:
" remove consecutive blank lines
" see Preserve function definition
" another way to remove blank lines :g/^$/,/./-j
" Reference: https://stackoverflow.com/a/7496112/2571881
if !exists('*DelBlankLines')
fun! DelBlankLines() range
if !&binary && &filetype != 'diff'
call Preserve(':%s/\s\+$//e')
call Preserve(':%s/^\n\{2,}/\r/ge')
call Preserve(':%s/\v($\n\s*)+%$/\r/e')
endif
endfun
endif
In my case, I keep at least one blank line, but not more than one, at the end of the file.
" Utility function that save last search and cursor position
" http://technotales.wordpress.com/2010/03/31/preserve-a-vim-function-that-keeps-your-state/
" video from vimcasts.org: http://vimcasts.org/episodes/tidying-whitespace
" using 'execute' command doesn't overwrite the last search pattern, so I
" don't need to store and restore it.
" preserve function
if !exists('*Preserve')
function! Preserve(command)
try
let l:win_view = winsaveview()
"silent! keepjumps keeppatterns execute a:command
silent! execute 'keeppatterns keepjumps ' . a:command
finally
call winrestview(l:win_view)
endtry
endfunction
endif
Here's why I have a separated Preserve function:
command! -nargs=0 Reindent :call Preserve('exec "normal! gg=G"')
" join lines keeping cursor position
nnoremap J :call Preserve(':join')<CR>
nnoremap <Leader>J :call Preserve(':join!')<CR>
" Reloads vimrc after saving but keep cursor position
if !exists('*ReloadVimrcFunction')
function! ReloadVimrcFunction()
call Preserve(':source $MYVIMRC')
" hi Normal guibg=NONE ctermbg=NONE
windo redraw
echom "Reloaded init.vim"
endfunction
endif
noremap <silent> <Leader>v :drop $MYVIMRC<cr>
command! -nargs=0 ReloadVimrc :call ReloadVimrcFunction()
" Strip trailing whitespaces
command! Cls :call Preserve(':%s/\v\s+$//e')
And if by any chance you want to create an autocommand you must create a group to avoid overloading autocommands:
augroup removetrailingspaces
au!
au! BufwritePre *.md,*.py,*.sh,*.zsh,*.txt :call Preserve(':%s/\v\s+$//e')
augroup END
This one is to change file headers (if you have any suggestions) feel free to interact:
" trying avoid searching history in this function
if !exists('*ChangeHeader')
fun! ChangeHeader() abort
if line('$')>=7
call Preserve(':1,7s/\v(Last (Change|Modified)|date):\s+\zs.*/\=strftime("%b %d, %Y - %H:%M")/ei')
endif
endfun
endif
" dos2unix ^M
if !exists('*Dos2unixFunction')
fun! Dos2unixFunction() abort
"call Preserve('%s/ $//ge')
call Preserve(":%s/\x0D$//e")
set ff=unix
set bomb
set encoding=utf-8
set fileencoding=utf-8
endfun
endif
com! Dos2Unix :call Dos2unixFunction()
精彩评论