1

Is it possible to show all changes made to a buffer since the buffer was opened?

This question https://stackoverflow.com/questions/749297/can-i-see-changes-before-i-save-my-file-in-vim is related, but asks for changes since the last write, which can easily be accomplished by looking at the file on the file system.

I am using persistent undo (set undofile), so I cannot use :earlier <reallylargenumber>.

  • Why can't you use undo? Are you saying you haven't configured it to save enough entries? Then add more! :) I mean, that's Vim's change history mechanism after all. – B Layer Dec 30 '18 at 15:14
  • :h DiffOrig provides a useful command for this – D. Ben Knoble Dec 30 '18 at 15:51
  • @BLayer I don't know how far to go in the undo tree. – Bananach Dec 30 '18 at 16:15
  • 1
    I guess you have to store highest undo sequence number from a autocmd on BufRead/BufReadPost using the function undotree(). Than you might be able to determine the value of for :earlier. – Ralf Dec 30 '18 at 16:27
  • @D.BenKnoble Contrary to what the help text says this seems to diff to the last saved state (when I change a file then save with :w, and then run the command, it shows no change) – Bananach Dec 30 '18 at 16:33
2

I played around. Could you try the following (rarely tested):

autocmd BufReadPost * let b:undo_seq_load=changenr()

function! DiffSinceLoad()
    let tmpa = tempname()
    let tmpb = tempname()
    let curchange=changenr()
    exe "undo " . b:undo_seq_load
    exec 'w '.tmpa
    exe "undo " . curchange
    exec 'w '.tmpb
    update
    exec 'tabnew '.tmpa
    diffthis
    vert split
    exec 'edit '.tmpb
    diffthis
endfunction
command! -nargs=0 DiffSinceLoad call DiffSinceLoad()

This is based on this answer.

Second iteration: This is now in my vimrc.

  • Use only one temporary file
  • If the buffer with the temporary file gets hidden, it is deleted.
  • When the buffer with the temporary file is deleted, :diffoff is called via autocmd.

 

" store the changenr at file load
autocmd BufReadPost * let b:changenr_on_load=changenr()
function! DiffSinceLoad()
    let tmpa = tempname()
    let curchange=changenr()
    exe "undo " . b:changenr_on_load
    exe 'w ' . tmpa
    exe 'undo ' . curchange
    "diffthis
    exe 'vertical diffsplit ' . tmpa
    " when buffer gets hidden, delete it and reset diff settings
    setlocal bufhidden=delete
    autocmd BufDelete <buffer> diffoff
    " return to edited file
    wincmd p
endfunction
command! -nargs=0 DiffSinceLoad silent call DiffSinceLoad()
  • I'm glad you understood what I needed. I'm currently wildly modifying my vimrc and sometimes just don't trust anything that was going on in my sessions. – Bananach Dec 30 '18 at 17:04
  • @Bananach Great if I could help. If you find problems with this script (as said I didn't really test it), report here so we could improve the answer. – Ralf Dec 30 '18 at 18:25
  • Is there a need for two temp files? If one side of the diff is the current state of the buffer in question I'd think you can just :split it (or :vert or whatever) and call :diffthis from the split window. – B Layer Dec 30 '18 at 21:37
  • 1
    @BLayer See update. – Ralf Dec 31 '18 at 1:19
  • Cool. Just FYI, you could combine the vsplit and two diffthis calls into a single command: exec "vert diffsplit ".tmpa. – B Layer Dec 31 '18 at 20:22
-1

This will do what you're looking for:

:w !diff % -
  • 1
    This shows the diffs since the last write, but not since loading the file. – Ralf Dec 30 '18 at 16:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.