Moshev
Moshev

Reputation: 566

How can I strip whitespace only from changed lines

I would like to configure Vim to only strip off the trailing whitespace from lines I've changed. My usecase is that a lot of the files in our repository have trailing whitespace on some of their lines and if I indiscriminately strip off all the trailing whitespace, then git blame shows me as the person who changed those lines. I would like to do this in Vim, rather than via a pre-commit hook, because I do not wish to have to reload the file in Vim, as that confuses my undo history.

Upvotes: 1

Views: 214

Answers (2)

Idan Arye
Idan Arye

Reputation: 12603

function! s:linesNotComitted(filename)
    let l:blameResult = system('git blame -sn ' . shellescape(a:filename))
    let l:blameResultLines = split(l:blameResult, "[\n\r]")
    let l:result = []
    for l:line in l:blameResultLines
        let l:match = matchlist(l:line, '\v^0+\s(\d+)')
        if !empty(l:match)
            call add(l:result, str2nr(l:match[1]))
        endif
    endfor
    return l:result
endfunction

function! s:stripTrailingWhitespaceFromLines(lineNumbers)
    for l:lineNumber in a:lineNumbers
        let l:line = getline(l:lineNumber)
        let l:modifiedLine = substitute(l:line, '\v\s+$', '', '')
        if l:line != l:modifiedLine
            call setline(l:lineNumber, l:modifiedLine)
        endif
    endfor
endfunction

command! StripTrailingWhitespaceFromNotComittedLines call s:stripTrailingWhitespaceFromLines(s:linesNotComitted(expand('%')))

Upvotes: 0

VanLaser
VanLaser

Reputation: 1164

I am not sure if this is what's you want (perhaps you want to use git blame etc. - ?), but, if you use the vim-gitgutter plugin, you can rely on the GitGutterGetHunks() function to implement something like this (just an idea):

function! s:removeTrailingSpacesFromHunks()
    let hunks = GitGutterGetHunks()
    for hunk in hunks
        let cmd = ':' . hunk[2] . ',' . (hunk[2] + hunk[3] - 1) . 's/\s\+$//e'
        "debug: display command
        echo cmd
        "run command
        execute cmd
    endfor
endfunction

command! FixMySpaces call <SID>removeTrailingSpacesFromHunks()

Of course, using that plugin, you can even skip this and simply look at the signs displayed on the left in order to visual-select the modified/added lines and call a substitute command, or a simple custom command wrapper that removes the trailing spaces for the manually selected range(s).

The command can be called before staging, any number of times (ideally, after saving - in any case, when signs/hunks are synchronized).

Upvotes: 1

Related Questions