不再搞乱VIM中的空白

时间:2012-01-09 14:08:10

标签: linux editor vim

我在BufWritePre添加了一个.vimrc钩子,用于在保存缓冲区之前修剪尾随空格。在编辑我自己的代码时,这对我来说非常方便,而其他人也有一个总是删除尾随空格的策略。然而,这使我有时搞乱了其他人的空白,这在版本控制中看起来不太好。

我有两个想法如何解决这个问题,我有两个具体的问题:

选项1

打开文件(可能使用BufReadPost挂钩)后,检测文件中是否有尾随空格。如果是,请设置缓冲区本地标志以发出此信号。如果设置了标志,请在保存前禁用修剪。

我对这种方法的问题是我似乎没有弄明白如何检测缓冲区中是否有尾随空格。我知道=~,但是如何将缓冲区内容作为字符串获取?或者甚至更好,我可以使用/\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>

3 个答案:

答案 0 :(得分:4)

选项1可以从search()函数中受益,如下所示:

let b:has_trailing_spaces=!!search('\v\s+$', 'cwn')

search()函数返回一些匹配的行(它们从1开始)或0如果没有找到,!!将其转换为1或0,删除有关哪一行{{1找到尾随空格。没有search()标志n移动光标,我猜,这是不受欢迎的。如果没有search(),它可能只搜索光标之后的缓冲区部分(实际上取决于w选项)。

建议的选项2实施是使用'wrapscan'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无法这样做,因此你必须写一些更复杂的东西,可能是在python中。我对其他VC系统一无所知。

我想如果你使用hg annotate来查看这些空格会更好,如果它们意外出现就能手动删除它们(个人我不记得自己经常偶然添加尾随空格,但是我故意用来表明该段继续的评论和文件。你怎么做才出现这个问题?

答案 1 :(得分:3)

我倾向于不让vim自动修剪任何东西。如你所说,如果处理其他人的代码,这可能是一场噩梦,并可能导致不必要的冲突。我采取的方法是保持自己的代码整洁是为了使空白可见。使用vim,可以通过在~/.vimrc文件中添加以下内容来实现:

highlight SpecialKey ctermfg=DarkGray
set listchars=tab:>-,trail:~
set list

结果是显示如下的空白:

vim show whitespace

这使我可以在编写文件时保持文件清洁。大多数其他(GUI)编辑器也能够显示空白。

答案 2 :(得分:2)

" Show trailing whitepace and spaces before a tab:
:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$\| \+\ze\t/
:autocmd ColorScheme * highlight ExtraWhitespace ctermbg=red guibg=red

这样任何坏的空白都会发红光。这很难错过。