Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
" It's probably not exactly what you want, because you mentioned autocmds in the original post, but you may be interested in :h :DiffOrig. FWIW, here's a modified version of this custom command which I'm using:
com! -bar DiffOrig echo s:diff_orig()
fu! s:diff_orig() abort
let cole_save = &l:cole
setl cole=0
vnew
setl bh=wipe nobl bt=nofile noswf
sil 0r #
$d_
diffthis
sil file Original\ File
nno <buffer><nowait><silent> q :<c-u>close<cr>
let &ft = getbufvar('#', '&ft')
setl noma ro
let s:tmp_partial = function('s:diff_orig_restore_settings', [cole_save])
augroup diff_orig_restore_settings
au! * <buffer>
au BufWipeOut <buffer> call timer_start(0, s:tmp_partial)
augroup END
exe winnr('#').'windo diffthis'
return ''
endfu
fu! s:diff_orig_restore_settings(cole,_) abort
exe 'setl cole='.a:cole
diffoff!
norm! zvzz
aug! diff_orig_restore_settings
unlet s:tmp_partial
endfu
" If you execute :DiffOrig in a buffer, it should open a vertical viewport displaying the contents of the original file, and all the differences between the current buffer and the latter.
" Edit:
" Alternatively, you could try this:
fu! s:snr()
return matchstr(expand('<sfile>'), '<SNR>\d\+_')
endfu
fu! s:diff_indicator() abort
if exists('b:diff_indicator')
return b:diff_indicator
endif
if !&l:modified || expand('%:p') == '' || &bt != ''
return ''
endif
let buf = getbufline('%', 1, '$')
let buf_max_lines = len(buf)
let file = readfile(expand('%:p'))
let file_max_lines = len(file)
if buf_max_lines != file_max_lines
let b:diff_indicator = '[!=]'
return b:diff_indicator
endif
for i in range(1,buf_max_lines)
if buf[i-1] !=# file[i-1]
let b:diff_indicator = '[!=]'
return b:diff_indicator
endif
endfor
let b:diff_indicator = '[==]'
return b:diff_indicator
endfu
let &stl .= ' %{'.s:snr().'diff_indicator()}'
augroup reset_diff_indicator
au!
au CursorHold * unlet! b:diff_indicator
augroup END
" It should add an indicator in the statusline, and update it every time CursorHold is fired. This event is fired every &updatetime ms (4s by default). If you find it's too long, you could reduce the value of the 'updatetime' option, or you could use a timer. In this case, you would replace the autocmd listening to CursorHold with this one:
" au VimEnter * call timer_start(1000, {-> execute('unlet! b:diff_indicator')}, {'repeat': -1})
" Here, the timer would cause the indicator to be updated every second, but you could change the value with whatever you prefer.
" Edit 2:
" If you notice a negative impact on Vim's performance, you may make listen your autocmd to TextChanged and TextChangedI. You would need to start a timer to reset the statusline indicator every time one of these events is fired. And prior to that, you would need to stop a possible previous timer. It would give something like:
fu! s:snr()
return matchstr(expand('<sfile>'), '<SNR>\d\+_')
endfu
fu! s:diff_indicator() abort
if !&l:modified || &l:buftype != '' || expand('%:p') == ''
return ''
endif
if exists('b:diff_indicator')
return b:diff_indicator
endif
let buf = getbufline('%', 1, '$')
let buf_max_lines = len(buf)
let file = readfile(expand('%:p'))
let file_max_lines = len(file)
if buf_max_lines != file_max_lines
let b:diff_indicator = '[!=]'
return b:diff_indicator
endif
for i in range(1,buf_max_lines)
if buf[i-1] !=# file[i-1]
let b:diff_indicator = '[!=]'
return b:diff_indicator
endif
endfor
let b:diff_indicator = '[==]'
return b:diff_indicator
endfu
let &stl .= ' %{'.s:snr().'diff_indicator()}'
augroup reset_diff_indicator
au!
au TextChanged,TextChangedI * call s:reset_diff_indicator()
augroup END
fu! s:reset_diff_indicator() abort
if exists('s:unlet_diff_indicator')
call timer_stop(s:unlet_diff_indicator)
endif
let s:unlet_diff_indicator = timer_start(500,
\ {-> execute('unlet! b:diff_indicator s:unlet_diff_indicator | redraws')})
endfu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.