仅删除已编辑行的尾随空白

发布于 2024-12-18 19:16:37 字数 1046 浏览 1 评论 0原文

我在 .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 负担。

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

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

I had added the following function in my .vimrc for removing trailing white spaces just before saving

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()

It works really well. However, in certain cases I would like to remove trailing white spaces only from lines that I have edited. This is to ensure that my diff output looks sane as for certain legacy code files almost all lines have trailing back spaces and I do not want to burden my code reviewer with unnecessary diff.

diff -b is not a solution right now since it also ignores white spaces from anywhere in a line and sometimes that change is important enough to be include in the diff output.

So my question is - is it possible to strip trailing white spaces from only the lines that have been edited in this session in a file in vim?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

难以启齿的温柔 2024-12-25 19:16:37

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

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

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

s/\s\+$//e

It will如果您包含的所有行不以白色结尾,则有效
空格,只有最后一个。可能会更改您没有更改的线路
已修改,如果您进入并退出插入模式(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 并在离开插入模式时检查它以检测更改。

One possibility would be to use autocmd InsertLeave to strip white spaces from current line every time you leave insert mode:

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

, and change substitute command of StripTrailingWhitespaces() function changed to

s/\s\+$//e

It will work if all lines that you include doesn't end in white
spaces, only the last one. It will possible change lines that you didn't
modified, if you enter and exit insert mode (i followed by ESC).

This solution can be changed to work if you include lines that does end in white space (pasted lines from legacy code, for example):

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     

If the replacement on lines due to enter and exit insert mode (i followed by ESC) is a problem then the solution could save b:changedtick-variable when entering insert mode and check it when leaving insert mode to detect changes.

面如桃花 2024-12-25 19:16:37

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

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()

或者,我编写了 一个插件,提供此更新的功能,以及一些附加功能,例如在正常模式下剥离。

mMontu's answer has the right idea, but it doesn't handle an edge case. Namely, if I move the cursor down, then back up, all in edit mode, it doesn't pick up the changes to those lines. If we would like to handle this, then we need to store the top and bottom lines visited by the user. Here is some more robust code, with everything grouped into functions:

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

Now we just invoke these functions at the right time:

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

Alternatively, I've written a plugin that provides this updated functionality, with several additional features like stripping in normal mode as well.

战皆罪 2024-12-25 19:16:37

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

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

let g:scavenger_auto_clean_up_on_write = 1

有关更多详细信息,您可以访问 Github 存储库了解更多。请随时给我改进插件的建议。

I write a plugin named 'vim-scavenger' to clean up multiple blank lines and trailing spaces.

Just add the following config in your .vimrc:

let g:scavenger_auto_clean_up_on_write = 1

For more detail, you can come to that Github repo to learn more. Feel free to give me advice to improve the plugin.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文