One problem is that the %
character only turns into the current buffer in Vim's command-line, but not when evaluated through system
. Instead, you should put expand('%')
and ideally wrap it in shellescape()
to ensure that any special characters are escaped for use in the shell.
Provided you have a recent enough Vim, you should also have the trim(
function to clean up some whitespace, so the function might look something like this:
function! GetGitDiffSummary()
let l:git_command = "git diff --numstat -- " . shellescape(expand('%'))
let l:adds = "+".trim(system(l:git_command . " | awk '{print($1)}'"))
let l:subs = "-".trim(system(l:git_command . " | awk '{print($2)}'"))
return l:adds."/".l:subs
endfunction
Problem 2: when I press and hold keys that move the cursor (arrow keys & hjkl) I get the respective characters printed out. They don't change the contents of the file, but I still see them.
This is a problem with performance. The system
call could potentially take a while, and it blocks Vim. It gets invoked every time you move the cursor, which is unnecessary for this particular check -- git will only see a change in lines when you write the buffer. So maybe something like this would work better:
augroup UpdateDiffSummary
autocmd!
autocmd BufReadPost * let b:git_diff_summary = GetGitDiffSummary()
autocmd BufWritePost * let b:git_diff_summary = GetGitDiffSummary()
augroup END
set statusline+=%{get(b:,'git_diff_summary')}
These autocommands should trigger when opening a file and when writing the buffer, which are the two moments when this data would change. The reason to use get(b:, 'git_diff_summary')
instead of b:git_diff_summary
is to avoid an error if that variable isn't set.
There's other optimizations that could be done -- you could make a single system call instead of two, and it might make sense to check if l:adds
and l:subs
are the empty string to replace them with 0. But this should work as a start, I think.