我有一个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/

10-14 01:36