Go (Golang) programming language comes with a tool called
go fmt. Its a code formatter, which formats your code automagically (alignments, alphabetic sorting, tabbing, spacing, idioms...). Its really awesome.
So I've found this little autocommand which utilizes it in Vim, each time buffer is saved to file.
au FileType go au BufWritePre <buffer> FmtFmt is a function that comes with Go vim plugin.
This is really great, but it has 1 problem. Each time formatter writes to buffer, it creates a jump in undo/redo history. Which becomes very painful when trying to undo/redo changes, since every 2nd change is formatter (making cursor jump to line 1).
So I am wondering, is there any way to discard latest change from undo/redo history after triggering
EDIT:Ok, so far I have:
au FileType go au BufWritePre <buffer> undojoin | FmtBut its not all good yet. According to
:h undojoin, undojoin is not allowed after undo. And sure enough, it fires an error when I try to
:w after an undo.
So how do I achieve something like this pseudo-code:
if lastAction != undo then au FileType go au BufWritePre <buffer> undojoin | Fmt end
If I get this last bit figured out, I think I have a solution.
I attempted to use @pepper_chino's answer but ran into issues where if fmt errors then vim would undo the last change prior to running
GoFmt. I worked around this in a long and slightly convoluted way:
" Fmt calls 'go fmt' to convert the file to go's format standards. This being " run often makes the undo buffer long and difficult to use. This function " wraps the Fmt function causing it to join the format with the last action. " This has to have a try/catch since you can't undojoin if the previous " command was itself an undo. function! GoFmt() " Save cursor/view info. let view = winsaveview() " Check if Fmt will succeed or not. If it will fail run again to populate location window. If it succeeds then we call it with an undojoin. " Copy the file to a temp file and attempt to run gofmt on it let TempFile = tempname() let SaveModified = &modified exe 'w ' . TempFile let &modified = SaveModified silent exe '! ' . g:gofmt_command . ' ' . TempFile call delete(TempFile) if v:shell_error " Execute Fmt to populate the location window silent Fmt else " Now that we know Fmt will succeed we can now run Fmt with its undo " joined to the previous edit in the current buffer try silent undojoin | silent Fmt catch endtry endif " Restore the saved cursor/view info. call winrestview(view) endfunction command! GoFmt call GoFmt()