Удаление пробела только для отредактированных строк - PullRequest
13 голосов
/ 29 ноября 2011

Я добавил следующую функцию в мой .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?

Ответы [ 3 ]

4 голосов
/ 29 ноября 2011

Можно использовать 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 при входе в режим вставки и проверить его при выходе из режима вставки для обнаружения изменений .

3 голосов
/ 30 мая 2015

Ответ 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()

В качестве альтернативы я написал плагин , который обеспечивает эту обновленную функциональность, с несколькими дополнительными функциями, такими как удаление в обычном режиме.

0 голосов
/ 30 апреля 2016

Я пишу плагин с именем ' vim-scavenger ' для очистки нескольких пустых строк и конечных пробелов.

Просто добавьте следующую конфигурацию в ваш .vimrc:

let g:scavenger_auto_clean_up_on_write = 1

Для получения более подробной информации вы можете обратиться к этому Github repo , чтобы узнать больше.Не стесняйтесь давать мне советы по улучшению плагина.

...