m (Fixed formatting, added to Syntax category, marked as duplicate) |
Tags: Visual edit apiedit rollback |
||
(35 intermediate revisions by 22 users not shown) | |||
Line 1: | Line 1: | ||
+ | {{TipImported |
||
− | {{review}} |
||
− | {{duplicate|396|721|811|1274}} |
||
− | {{Tip |
||
|id=878 |
|id=878 |
||
+ | |previous=876 |
||
− | |title=Remove trailing spaces |
||
+ | |next=879 |
||
− | |created= |
+ | |created=2005 |
|complexity=intermediate |
|complexity=intermediate |
||
− | |author=Bertram Scharpf |
+ | |author=Bertram Scharpf |
− | |version= |
+ | |version=6.0 |
|rating=0/4 |
|rating=0/4 |
||
+ | |category1=Syntax |
||
− | |text= |
||
+ | |category2= |
||
− | A heavy nuisance to me are hidden spaces at line ends and before tab characters. I make them visible and remove them using two mappings: |
||
⚫ | |||
+ | |||
+ | == Simple commands to remove unwanted whitespace == |
||
+ | In a search, <code>\s</code> finds whitespace (a space or a tab), and <code>\+</code> finds one or more occurrences. |
||
+ | |||
+ | ==== Delete all trailing whitespace (at the end of each line) with: ==== |
||
+ | <pre> |
||
⚫ | |||
+ | </pre> |
||
+ | |||
+ | Like with ''ed(1)'', the substitution text can be omitted if blank: |
||
+ | <pre> |
||
+ | :%s/\s\+$ |
||
+ | </pre> |
||
+ | |||
+ | More rarely, a user might want to delete (leading) whitespace at the beginning of each line: |
||
+ | <pre> |
||
+ | :%s/^\s\+ |
||
+ | " Same thing (:le = :left = left-align given range): |
||
+ | :%le |
||
+ | </pre> |
||
+ | |||
+ | With the following mapping a user can press F5 to delete all trailing whitespace. The variable <code>_s</code> is used to save and restore the last search pattern register (so next time the user presses <code>n</code> they will continue their last search), and <code>:nohl</code> is used to switch off search highlighting (so trailing spaces will not be highlighted while the user types). The <code>e</code> flag is used in the substitute command so no error is shown if trailing whitespace is not found. Unlike before, the substitution text must be specified in order to use the required flag. |
||
+ | <pre> |
||
+ | :nnoremap <silent> <F5> :let _s=@/<Bar>:%s/\s\+$//e<Bar>:let @/=_s<Bar>:nohl<CR> |
||
+ | </pre> |
||
+ | |||
+ | See [[VimTip396|Highlighting whitespaces at end of line]] to display, rather than delete, unwanted whitespace. |
||
+ | |||
+ | ==Display or remove unwanted whitespace with a script== |
||
+ | The following is a more elaborate procedure that can display or remove unwanted whitespace. Here, "unwanted" means any spaces before a tab character, or any space or tab at the end of a line. |
||
+ | |||
<pre> |
<pre> |
||
− | function ShowSpaces( |
+ | function ShowSpaces(...) |
− | let @/= |
+ | let @/='\v(\s+$)|( +\ze\t)' |
let oldhlsearch=&hlsearch |
let oldhlsearch=&hlsearch |
||
if !a:0 |
if !a:0 |
||
Line 24: | Line 55: | ||
function TrimSpaces() range |
function TrimSpaces() range |
||
− | let oldhlsearch=ShowSpaces( |
+ | let oldhlsearch=ShowSpaces(1) |
execute a:firstline.",".a:lastline."substitute ///gec" |
execute a:firstline.",".a:lastline."substitute ///gec" |
||
let &hlsearch=oldhlsearch |
let &hlsearch=oldhlsearch |
||
Line 31: | Line 62: | ||
command -bar -nargs=? ShowSpaces call ShowSpaces(<args>) |
command -bar -nargs=? ShowSpaces call ShowSpaces(<args>) |
||
command -bar -nargs=0 -range=% TrimSpaces <line1>,<line2>call TrimSpaces() |
command -bar -nargs=0 -range=% TrimSpaces <line1>,<line2>call TrimSpaces() |
||
− | nnoremap <F12> :ShowSpaces 1< |
+ | nnoremap <F12> :ShowSpaces 1<CR> |
− | nnoremap <S-F12> m`:TrimSpaces< |
+ | nnoremap <S-F12> m`:TrimSpaces<CR>`` |
− | vnoremap <S-F12> :TrimSpaces< |
+ | vnoremap <S-F12> :TrimSpaces<CR> |
</pre> |
</pre> |
||
+ | This is a similar function which similates the manual steps for removing the whitespace. |
||
⚫ | |||
+ | <pre> |
||
+ | function StripTrailingWhitespace() |
||
+ | if !&binary && &filetype != 'diff' |
||
+ | normal mz |
||
+ | normal Hmy |
||
+ | %s/\s\+$//e |
||
+ | normal 'yz<CR> |
||
+ | normal `z |
||
+ | endif |
||
+ | endfunction |
||
+ | </pre> |
||
+ | However, this has minor side-effects, such as influencing undo history and sometimes changing scroll position. |
||
+ | ==Automatically removing all trailing whitespace== |
||
⚫ | |||
+ | One way to make sure to remove all trailing whitespace in a file is to set an <code>autocmd</code> in your .vimrc file. Every time the user issues a <code>:w</code> command, Vim will automatically remove all trailing whitespace before saving. |
||
− | Have you tried |
||
<pre> |
<pre> |
||
⚫ | |||
− | :set list |
||
⚫ | |||
</pre> |
</pre> |
||
− | List mode: Show tabs as CTRL-I, show end of line with $. Useful to |
||
− | see the difference between tabs and spaces and for trailing blanks. |
||
− | Note that this will also affect formatting (set with 'textwidth' or |
||
− | 'wrapmargin') when 'cpoptions' includes 'L'. See 'listchars' for |
||
− | changing the way tabs are displayed. |
||
+ | However, this is a very dangerous autocmd to have as it will always strip trailing whitespace from every file a user saves. Sometimes, trailing whitespace is desired, or even essential in a file so be careful when implementing this <code>autocmd</code>. |
||
+ | One method to mitigate this issue in a .vimrc file, where trailing whitespace matters, is to change how .vimrc prepends wrapped lines. For example, add the following into the .vimrc: |
||
− | Panchali Das Gupta |
||
− | , February 18, 2005 10:40 |
||
⚫ | |||
− | Have you tried to add: |
||
<pre> |
<pre> |
||
+ | set wrap |
||
− | let c_space_errors=1 |
||
+ | set linebreak |
||
+ | " note trailing space at end of next line |
||
+ | set showbreak=>\ \ \ |
||
</pre> |
</pre> |
||
+ | Now when saving the .vimrc it will use <code>"> \"</code> instead of <code>"> "</code> to prepend wrapped lines. |
||
− | before the 'syntax on' in your .vimrc? |
||
+ | A user can also specify a particular filetype in an <code>autocmd</code> so that only that filetype will be changed when saving. The following only changes files with the extension .pl: |
||
− | hoogenboom30--AT--zonnet.nl |
||
+ | <pre> |
||
− | , February 19, 2005 7:27 |
||
+ | autocmd BufWritePre *.pl :%s/\s\+$//e |
||
⚫ | |||
+ | </pre> |
||
− | I know of c_space_errors. First, in my opinion, trailing spaces are legal C syntax. So why mention it withing syntax highlighting? |
||
+ | Additionally, a FileType autocommand can be used to restrict the <code>autocmd</code> to certain file types only. |
||
− | Second, this only works for C and several other file types. I would like to have it with _every_ file. |
||
+ | <pre> |
||
+ | autocmd FileType c,cpp,java,php autocmd BufWritePre <buffer> :%s/\s\+$//e |
||
+ | </pre> |
||
+ | ==See also== |
||
− | Third, I'm annoyed by spaces being highlighted during typing and I like to switch that off. |
||
+ | *{{help|:autocmd}} - Additional information on <code>autocmd</code> |
||
+ | ==Related scripts== |
||
− | Bertram Scharpf |
||
+ | * The {{script|id=3967|text=DeleteTrailingWhitespace}} plugin offers a eponymous command, and can remove trailing whitespace automatically when the buffer is written. |
||
− | , February 20, 2005 10:50 |
||
+ | * The {{script|id=3201|text=trailing-whitespace}} plugin defines :FixWhitespace. |
||
⚫ | |||
+ | * The {{script|id=3735|text=bad-whitespace}} plugin defines :EraseBadWhitespace. |
||
⚫ | |||
+ | * The {{script|id=3938|text=Trailer Trash}} plugin defines :Trim. |
||
+ | |||
⚫ | |||
⚫ | |||
<pre> |
<pre> |
||
− | " Removes trailing spaces |
+ | " Removes trailing spaces |
− | function TrimWhiteSpace() |
+ | function TrimWhiteSpace() |
− | + | %s/\s*$// |
|
− | + | '' |
|
− | :endfunction |
+ | :endfunction |
− | set list listchars=trail:.,extends: |
+ | set list listchars=trail:.,extends:> |
− | autocmd FileWritePre * :call TrimWhiteSpace() |
+ | autocmd FileWritePre * :call TrimWhiteSpace() |
− | autocmd FileAppendPre * :call TrimWhiteSpace() |
+ | autocmd FileAppendPre * :call TrimWhiteSpace() |
− | autocmd FilterWritePre * :call TrimWhiteSpace() |
+ | autocmd FilterWritePre * :call TrimWhiteSpace() |
− | autocmd BufWritePre * :call TrimWhiteSpace() |
+ | autocmd BufWritePre * :call TrimWhiteSpace() |
− | map |
+ | map <F2> :call TrimWhiteSpace()<CR> |
− | map! |
+ | map! <F2> :call TrimWhiteSpace()<CR> |
− | |||
− | It works for me. |
||
− | michael--AT--jarvis.com, February 21, 2005 13:52 |
||
</pre> |
</pre> |
||
+ | |||
---- |
---- |
||
− | My |
+ | My preferred setting of list and listchars so that I can see my whitespace instead of removing it: |
<pre> |
<pre> |
||
− | set list listchars=tab: |
+ | set list listchars=tab:»·,trail:· |
</pre> |
</pre> |
||
− | This yields to: |
||
⚫ | |||
+ | This gives:<br> |
||
− | thomas--AT--intevation.de |
||
⚫ | |||
− | , February 21, 2005 23:30 |
||
+ | |||
+ | Or try |
||
+ | <pre> |
||
+ | set list lcs=tab:·⁖,trail:¶ |
||
+ | </pre> |
||
+ | |||
+ | This gives:<br> |
||
+ | ·⁖⁖⁖⁖⁖⁖⁖text after tab with four spaces after it¶¶¶¶ |
||
---- |
---- |
||
− | There is one occasion where I want to keep my trailing space. But even in those documents, I want to keep it in only one place, and not every |
+ | There is one occasion where I want to keep my trailing space. But even in those documents, I want to keep it in only in one place, and not every occurrence. |
− | Here is my substitution pattern: |
+ | Here is my substitution pattern: |
<pre> |
<pre> |
||
− | + | s/\(^--\)\@<!\s*$// |
|
</pre> |
</pre> |
||
⚫ | |||
⚫ | |||
⚫ | |||
+ | |||
⚫ | |||
⚫ | |||
+ | <pre> |
||
⚫ | |||
+ | </pre> |
||
+ | |||
⚫ | |||
+ | <pre> |
||
⚫ | |||
⚫ | |||
⚫ | |||
+ | autocmd BufWritePre * :TrimSpaces |
||
+ | </pre> |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
(taking advantage of the default range defined in Betram's command definition) |
(taking advantage of the default range defined in Betram's command definition) |
||
− | NOa.wagnerSP--AT--Mstud.uni-frankfurt.de |
||
− | , April 19, 2005 2:21 |
||
---- |
---- |
||
+ | I modified one of the above scripts to let the user know if whitespace was found |
||
− | Be careful if you are editing shell scripts while using this. |
||
+ | <pre> |
||
− | IFS= is cleared! |
||
+ | " automatically remove trailing whitespace before write |
||
+ | function! StripTrailingWhitespace() |
||
+ | normal mZ |
||
+ | %s/\s\+$//e |
||
+ | if line("'Z") != line(".") |
||
+ | echo "Stripped whitespace\n" |
||
+ | endif |
||
+ | normal `Z |
||
+ | endfunction |
||
+ | autocmd BufWritePre *.cpp,*.hpp,*.i :call StripTrailingWhitespace() |
||
+ | </pre> |
||
− | '''Anonymous''' |
||
− | , March 17, 2006 2:33 |
||
---- |
---- |
||
+ | I didn't get the <code>*</code> match to work so I used <code>*.*</code> instead: |
||
− | [[Category:Syntax]] |
||
+ | <pre> |
||
+ | autocmd BufWritePre *.* :%s/\s\+$//e |
||
+ | </pre> |
||
+ | |||
⚫ | |||
+ | Marks are unnecessary, at least in Vim 7. (Yes, that *.{cpp,h,c,etc} syntax is valid. Much better than *.cpp,*.h,*.c,*.etc IMHO.) |
||
+ | |||
+ | <pre> |
||
+ | autocmd BufWritePre *.{cpp,h,c,etc} call StripTrailingWhite() |
||
+ | |||
+ | function! StripTrailingWhite() |
||
+ | let l:winview = winsaveview() |
||
+ | silent! %s/\s\+$// |
||
+ | call winrestview(l:winview) |
||
+ | endfunction |
||
+ | </pre> |
||
⚫ | |||
+ | Actually because %s seems like is forcing a redraw line by line (is a guess), I get faster result by entering EX mode first: |
||
+ | <pre> |
||
+ | autocmd BufWritePre <Esc>Q :call StripTailingWhite()<CR>:visual<CR> |
||
+ | </pre> |
||
+ | This was a guess that worked but my limited knowledge can't answer why |
||
⚫ | |||
+ | |||
+ | I like the one above that prints a message. In that case I think the mark is needed. However, there is a small bug in the implementation that fails to print the message if the current line has trailing whitespace and is the last line or only line in the file that does. Checking also for change in the number of chars in the current line fixes it. |
||
+ | |||
+ | <pre> |
||
+ | function! StripTrailingWhitespace() |
||
+ | normal mZ |
||
+ | let l:chars = col("$") |
||
+ | %s/\s\+$//e |
||
+ | if (line("'Z") != line(".")) || (l:chars != col("$")) |
||
+ | echo "Trailing whitespace stripped\n" |
||
+ | endif |
||
+ | normal `Z |
||
+ | endfunction |
||
+ | |||
+ | autocmd BufWritePre * :call StripTrailingWhitespace() |
||
+ | </pre> |
Revision as of 23:53, 20 August 2015
created 2005 · complexity intermediate · author Bertram Scharpf · version 6.0
Simple commands to remove unwanted whitespace
In a search, \s
finds whitespace (a space or a tab), and \+
finds one or more occurrences.
Delete all trailing whitespace (at the end of each line) with:
:%s/\s\+$//
Like with ed(1), the substitution text can be omitted if blank:
:%s/\s\+$
More rarely, a user might want to delete (leading) whitespace at the beginning of each line:
:%s/^\s\+ " Same thing (:le = :left = left-align given range): :%le
With the following mapping a user can press F5 to delete all trailing whitespace. The variable _s
is used to save and restore the last search pattern register (so next time the user presses n
they will continue their last search), and :nohl
is used to switch off search highlighting (so trailing spaces will not be highlighted while the user types). The e
flag is used in the substitute command so no error is shown if trailing whitespace is not found. Unlike before, the substitution text must be specified in order to use the required flag.
:nnoremap <silent> <F5> :let _s=@/<Bar>:%s/\s\+$//e<Bar>:let @/=_s<Bar>:nohl<CR>
See Highlighting whitespaces at end of line to display, rather than delete, unwanted whitespace.
Display or remove unwanted whitespace with a script
The following is a more elaborate procedure that can display or remove unwanted whitespace. Here, "unwanted" means any spaces before a tab character, or any space or tab at the end of a line.
function ShowSpaces(...) let @/='\v(\s+$)|( +\ze\t)' let oldhlsearch=&hlsearch if !a:0 let &hlsearch=!&hlsearch else let &hlsearch=a:1 end return oldhlsearch endfunction function TrimSpaces() range let oldhlsearch=ShowSpaces(1) execute a:firstline.",".a:lastline."substitute ///gec" let &hlsearch=oldhlsearch endfunction command -bar -nargs=? ShowSpaces call ShowSpaces(<args>) command -bar -nargs=0 -range=% TrimSpaces <line1>,<line2>call TrimSpaces() nnoremap <F12> :ShowSpaces 1<CR> nnoremap <S-F12> m`:TrimSpaces<CR>`` vnoremap <S-F12> :TrimSpaces<CR>
This is a similar function which similates the manual steps for removing the whitespace.
function StripTrailingWhitespace() if !&binary && &filetype != 'diff' normal mz normal Hmy %s/\s\+$//e normal 'yz<CR> normal `z endif endfunction
However, this has minor side-effects, such as influencing undo history and sometimes changing scroll position.
Automatically removing all trailing whitespace
One way to make sure to remove all trailing whitespace in a file is to set an autocmd
in your .vimrc file. Every time the user issues a :w
command, Vim will automatically remove all trailing whitespace before saving.
autocmd BufWritePre * :%s/\s\+$//e
However, this is a very dangerous autocmd to have as it will always strip trailing whitespace from every file a user saves. Sometimes, trailing whitespace is desired, or even essential in a file so be careful when implementing this autocmd
.
One method to mitigate this issue in a .vimrc file, where trailing whitespace matters, is to change how .vimrc prepends wrapped lines. For example, add the following into the .vimrc:
set wrap set linebreak " note trailing space at end of next line set showbreak=>\ \ \
Now when saving the .vimrc it will use "> \"
instead of "> "
to prepend wrapped lines.
A user can also specify a particular filetype in an autocmd
so that only that filetype will be changed when saving. The following only changes files with the extension .pl:
autocmd BufWritePre *.pl :%s/\s\+$//e
Additionally, a FileType autocommand can be used to restrict the autocmd
to certain file types only.
autocmd FileType c,cpp,java,php autocmd BufWritePre <buffer> :%s/\s\+$//e
See also
- :help :autocmd - Additional information on
autocmd
Related scripts
- The DeleteTrailingWhitespace plugin offers a eponymous command, and can remove trailing whitespace automatically when the buffer is written.
- The trailing-whitespace plugin defines :FixWhitespace.
- The bad-whitespace plugin defines :EraseBadWhitespace.
- The Trailer Trash plugin defines :Trim.
Comments
Here's what I use in my .vimrc:
" Removes trailing spaces function TrimWhiteSpace() %s/\s*$// '' :endfunction set list listchars=trail:.,extends:> autocmd FileWritePre * :call TrimWhiteSpace() autocmd FileAppendPre * :call TrimWhiteSpace() autocmd FilterWritePre * :call TrimWhiteSpace() autocmd BufWritePre * :call TrimWhiteSpace() map <F2> :call TrimWhiteSpace()<CR> map! <F2> :call TrimWhiteSpace()<CR>
My preferred setting of list and listchars so that I can see my whitespace instead of removing it:
set list listchars=tab:»·,trail:·
This gives:
»·······text after tab with four spaces after it····
Or try
set list lcs=tab:·⁖,trail:¶
This gives:
·⁖⁖⁖⁖⁖⁖⁖text after tab with four spaces after it¶¶¶¶
There is one occasion where I want to keep my trailing space. But even in those documents, I want to keep it in only in one place, and not every occurrence.
Here is my substitution pattern:
s/\(^--\)\@<!\s*$//
This will eliminate all trailing whitespaces except for the one in an email signature marker (-- ). See wikipedia:Signature block.
In the function in the tip, this expands to:
execute a:firstline.",".a:lastline."substitute /\\(^--\\)\\@<!\\s*$//ge"
Also, I've found the autocmds to work better like this:
autocmd FileWritePre * :TrimSpaces autocmd FileAppendPre * :TrimSpaces autocmd FilterWritePre * :TrimSpaces autocmd BufWritePre * :TrimSpaces
(taking advantage of the default range defined in Betram's command definition)
I modified one of the above scripts to let the user know if whitespace was found
" automatically remove trailing whitespace before write function! StripTrailingWhitespace() normal mZ %s/\s\+$//e if line("'Z") != line(".") echo "Stripped whitespace\n" endif normal `Z endfunction autocmd BufWritePre *.cpp,*.hpp,*.i :call StripTrailingWhitespace()
I didn't get the *
match to work so I used *.*
instead:
autocmd BufWritePre *.* :%s/\s\+$//e
Marks are unnecessary, at least in Vim 7. (Yes, that *.{cpp,h,c,etc} syntax is valid. Much better than *.cpp,*.h,*.c,*.etc IMHO.)
autocmd BufWritePre *.{cpp,h,c,etc} call StripTrailingWhite() function! StripTrailingWhite() let l:winview = winsaveview() silent! %s/\s\+$// call winrestview(l:winview) endfunction
Actually because %s seems like is forcing a redraw line by line (is a guess), I get faster result by entering EX mode first:
autocmd BufWritePre <Esc>Q :call StripTailingWhite()<CR>:visual<CR>
This was a guess that worked but my limited knowledge can't answer why
I like the one above that prints a message. In that case I think the mark is needed. However, there is a small bug in the implementation that fails to print the message if the current line has trailing whitespace and is the last line or only line in the file that does. Checking also for change in the number of chars in the current line fixes it.
function! StripTrailingWhitespace() normal mZ let l:chars = col("$") %s/\s\+$//e if (line("'Z") != line(".")) || (l:chars != col("$")) echo "Trailing whitespace stripped\n" endif normal `Z endfunction autocmd BufWritePre * :call StripTrailingWhitespace()