我有一个BufWritePre
钩子(Hook)添加到我的.vimrc
中,该钩子(Hook)在保存缓冲区之前修剪尾随空白。当我编辑自己的代码或其他也有始终删除尾随空格的策略的代码时,这对我来说非常方便。但是,这有时使我困惑了其他人的空白,这在版本控制中看起来不太好。
我有两个想法通常可以解决,但我都存在以下特定问题:
选项1
打开文件后(可能使用BufReadPost
钩子(Hook)),检测文件中是否有尾随空格。如果是,则设置一个本地缓冲区标志来发出信号。如果设置了该标志,请在保存之前禁用修整。
这种方法的问题在于,我似乎并没有弄清楚如何检测缓冲区中是否存在尾随空格。我知道=~
,但是如何获取缓冲区内容作为字符串?甚至更好的是,我可以使用/\s+$<cr>
进行搜索,但是如何检查搜索是否成功(如果有命中)?
选项2(更智能)
如果仅在实际修改的行上进行空白修剪,那就更好了。这样,我可以不必在代码中尾随空格,而又不会弄乱文件的其余部分,从而受益。这就提出了一个问题:我能以某种方式获得我添加或修改的行的行号吗?
我是Vimscript的新手,所以不胜感激:)
更新:我现在选择了选项1:
" configure list facility
highlight SpecialKey term=standout ctermbg=yellow guibg=yellow
set listchars=tab:>-,trail:~
" determine whether the current file has trailing whitespace
function! SetWhitespaceMode()
let b:has_trailing_whitespace=!!search('\v\s+$', 'cwn')
if b:has_trailing_whitespace
" if yes, we want to enable list for this file
set list
else
set nolist
endif
endfunction
" trim trailing whitespace in the current file
function! RTrim()
%s/\v\s+$//e
noh
endfunction
" trim trailing whitespace in the given range
function! RTrimRange() range
exec a:firstline.",".a:lastline."substitute /\\v\\s+$//e"
endfunction
" after opening and saving files, check the whitespace mode
autocmd BufReadPost * call SetWhitespaceMode()
autocmd BufWritePost * call SetWhitespaceMode()
" on save, remove trailing whitespace if there was already trailing whitespace
" in the file before
autocmd BufWritePre * if !b:has_trailing_whitespace | call RTrim() | endif
" strip whitespace manually
nmap <silent> <leader>W :call RTrim()<cr>
vmap <silent> <leader>W :call RTrimRange()<cr>
最佳答案
选项1可以受益于search()
函数,如下所示:
let b:has_trailing_spaces=!!search('\v\s+$', 'cwn')
search()
函数返回匹配的行数(它们从1开始)或0(如果未找到任何内容),!!
将其转换为1或0,丢弃有关在哪一行search()
尾随空白的信息。没有n
标志search()
会移动光标,我猜这是不希望的。如果没有w
,它可能仅在光标之后的缓冲区部分中搜索(实际上取决于'wrapscan'
选项)。建议的方案2实现是使用
InsertLeave
和'[
标记,']
标记的黑客:augroup CleanInsertedTrailingSpaces
autocmd!
autocmd InsertLeave * let wv=winsaveview() | keepjumps lockmarks '[,']s/\s\+$//e | call winrestview(wv)
augroup END
假定您仅在键入后添加尾随空格。如果您在插入模式下将光标跨行移动,它将中断。您也可以尝试添加
autocmd CursorHold * if getpos("'.")[1]!=0 | let wv=winsaveview() | keepjumps lockmarks '.s/\s\+$//e | call winrestview(wv) | endif
,这应该删除最后更改行的尾随空格(此处只能使用一行,
'[
和']
,因为它们指向第一行和最后一行通常很有用)。这两个自动命令都应将信息添加到撤消树中。选项2还有第二个选项:
git annotate
能够注释文件的当前状态,因此您可以使用grep
过滤出同时包含尾随空格和未提交更改的行,并使用钩子(Hook)在提交之前清除它们中不需要的空格。令人遗憾的是,但是hg annotate
无法做到这一点,因此您将不得不编写更复杂的内容(可能使用python)。关于其他VC系统,我无话可说。我想如果您使用
set list listchars+=trail:-
看到这样的空格并因此能够在它们意外出现时手动删除它们会更好(我个人不记得自己经常不小心添加尾随空格,尽管在注释和文档中它们被我有意指出该段继续)。您如何处理才能出现此问题?关于linux - 不再弄乱VIM中的空白,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8789666/