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>.

5
  • 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, 2018 at 15:14
  • :h DiffOrig provides a useful command for this
    – D. Ben Knoble
    Dec 30, 2018 at 15:51
  • @BLayer I don't know how far to go in the undo tree.
    – Bananach
    Dec 30, 2018 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, 2018 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, 2018 at 16:33

2 Answers 2

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()
5
  • 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, 2018 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, 2018 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, 2018 at 21:37
  • 1
    @BLayer See update.
    – Ralf
    Dec 31, 2018 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, 2018 at 20:22
-1

This will do what you're looking for:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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