11

I have these lines in my .vimrc to help with indentation:

autocmd BufReadPost * set noexpandtab | retab! 4
autocmd BufWritePre * set expandtab | retab! 4
autocmd BufWritePost * set noexpandtab | retab! 4

However, they create a lot of noise in the undo history. Since they essentially do nothing from the user's perspective, I'd like to remove them from the history or at the very least squash them somehow (perhaps they cancel out if squashed together?). Is there a way to do so?

1

3 Answers 3

7

For those who have this problem and wonder how to work around it without silencing all the errors, here is how I did it in my .vimrc:

au BufWritePre * try | undojoin | Neoformat | catch /^Vim\%((\a\+)\)\=:E790/ | endtry

Credit goes to Christian Brabandt and to this answer from Randy Morris

3
  • It should probably be noted that the Neoformat bit is only necessary if you're using the neoformat plugin, and will cause problems if you don't have it.
    – 8bittree
    Commented Aug 28, 2017 at 15:53
  • Well yes, the command is up to you, thank you for pointing it out!
    – Kjir
    Commented Aug 29, 2017 at 5:57
  • shouldn't the Neoformat command come at the end (or rather in a finally block)? Otherwise it wouldn't be executed if :undojoin throws an error. Commented Aug 31, 2017 at 12:21
4

Using undojoin actually works pretty well:

autocmd BufReadPost *  undojoin | set noexpandtab | retab! 4
autocmd BufWritePre *  undojoin | set expandtab   | retab! 4
autocmd BufWritePost * undojoin | set noexpandtab | retab! 4

However, if you execute :w right after undoing an action, you'll get an error:

Error detected while processing BufWritePre Auto commands for "*":
E790: undojoin is not allowed after undo
Error detected while processing BufWritePost Auto commands for "*":
E790: undojoin is not allowed after undo

This error can be silenced using silent! as mentioned in the comments, but may have some unintentional side effects:

autocmd BufReadPost *  silent! undojoin | set noexpandtab | retab! 4
autocmd BufWritePre *  silent! undojoin | set expandtab   | retab! 4
autocmd BufWritePost * silent! undojoin | set noexpandtab | retab! 4
3
  • 2
    undojoin is not allowed after an undo has been done. You cannot change those undo entries then. Therefore you see the error. As far as I know, there you cannot check this condition, so you might want to wrap this into an try|catch clause for E790 or simply use :sil! to silence the warning. Commented Nov 18, 2016 at 7:02
  • @ChristianBrabandt Is there a difference between the two techniques?
    – user8048
    Commented Nov 19, 2016 at 2:41
  • yes, one does silence a particula error, the other silences every error Commented Nov 19, 2016 at 16:24
0

I realize this is an old thread but thought I'd share that I recently discovered :h clear-undo and have found an alternative approach using 'undolevels'. The following example updates a revision date, excluding it from the undo history. Note this happens after the buffer or file is read and not before it is written. The winview lines keep the original cursor position.

function! LastMod()
    let l:winview = winsaveview()

    " from :h clear-undo
    let old_undolevels = &undolevels
    set undolevels=-1
    
    execute "silent!" '%s/\(revised: \)\d\{4}-\d\{2}-\d\{2}/\1'.strftime("%Y-%m-%d")
        
    " from :h clear-undo
    let &undolevels = old_undolevels
    unlet old_undolevels
    
    call winrestview(l:winview)
endfunction

autocmd BufReadPost,FileReadPost * call LastMod()

Your Answer

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