仅为已编辑的行删除尾随空格

时间:2011-11-29 11:09:32

标签: vim diff whitespace

我在.vimrc中添加了以下函数,用于在保存

之前删除尾随空格
fun! <SID>StripTrailingWhitespaces()                                            
    let l = line(".")                                                           
    let c = col(".")                                                            
    %s/\s\+$//e                                                                 
    call cursor(l, c)                                                           
endfun                                                                          

autocmd BufWritePre *.h :call <SID>StripTrailingWhitespaces()
autocmd BufWritePre *.cpp :call <SID>StripTrailingWhitespaces()
autocmd BufWritePre *.c :call <SID>StripTrailingWhitespaces()

效果很好。但是,在某些情况下,我想从我编辑过的行中删除尾随空格。这是为了确保我的diff输出对于某些遗留代码文件看起来很清晰,几乎所有行都有尾随空格,我不想让我的代码审阅者负担不必要的差异。

diff -b现在不是解决方案,因为它也会忽略行中任何位置的空格,有时这种更改非常重要,可以包含在diff输出中。

所以我的问题是 - 是否可以在vim的文件中仅删除此会话中已编辑的行的尾随空格?

3 个答案:

答案 0 :(得分:4)

一种可能性是每次离开插入模式时使用autocmd InsertLeave从当前行中去除空格:

autocmd InsertLeave *.[ch] :call <SID>StripTrailingWhitespaces()

,并将StripTrailingWhitespaces()函数的替换命令更改为

s/\s\+$//e

如果您包含的所有行都不以白色结尾,它将起作用 空间,只有最后一个。它可能会改变你没有的线 已修改,如果您进入和退出插入模式(i后跟ESC)。

如果您包含以空格结尾的行(例如旧版代码中的粘贴行),则可以将此解决方案更改为可用:

autocmd InsertEnter *.[ch] :let b:insert_start = line('.')
autocmd InsertLeave *.[ch] :call <SID>StripTrailingWhitespaces()

fun! StripTrailingWhitespaces()
    let original_cursor = getpos('.')
    exe b:insert_start . ',.s/\s\+$//e'
    call setpos('.', original_cursor)
endfun     

如果由于进入和退出插入模式(i后跟ESC)导致的替换是一个问题,那么解决方案可以在进入插入模式时保存b:changedtick-variable并在何时进行检查离开插入模式以检测变化。

答案 1 :(得分:3)

mMontu's answer有正确的想法,但它没有处理边缘情况。也就是说,如果我向下移动光标,然后备份,全部处于编辑模式,它不会获取对这些行的更改。如果我们想要处理这个问题,那么我们需要存储用户访问的顶线和底线。这里有一些更健壮的代码,所有内容都分为函数:

fun! <SID>SetupTrailingWhitespaces()
    let curline = line('.')
    let b:insert_top = curline
    let b:insert_bottom = curline
endfun

fun! <SID>UpdateTrailingWhitespace()
    let curline = line('.')
    if b:insert_top > curline
        let b:insert_top = curline
    elseif b:insert_bottom < curline
        let b:insert_bottom = curline
    endif
endfun

fun! <SID>StripTrailingWhitespaces()
    let original_cursor = getpos('.')
    exe b:insert_top ',' b:insert_bottom 's/\s\+$//e'
    call setpos('.', original_cursor)
endfun

现在我们只是在合适的时间调用这些函数:

autocmd InsertEnter * :call <SID>SetupTrailingWhitespaces()
autocmd InsertLeave * :call <SID>StripTrailingWhitespaces()
autocmd CursorMovedI * :call <SID>UpdateTrailingWhitespace()

或者,我写了a plugin来提供这个更新的功能,还有一些额外的功能,比如正常模式下的剥离。

答案 2 :(得分:0)

我编写了一个名为“vim-scavenger”的插件来清理多个空白行和尾随空格。

只需在.vimrc中添加以下配置:

let g:scavenger_auto_clean_up_on_write = 1

有关详细信息,您可以访问Github repo了解详情。随意给我建议改进插件。