go fmt
的工具。它是一个代码格式化程序,可以自动格式化代码(对齐,字母排序,制表,间距,习语......)。它非常棒。
所以我发现这个小自动命令在Vim中使用它,每次缓冲区都保存到文件中。
au FileType go au BufWritePre <buffer> Fmt
Fmt是Go vim插件附带的一个功能。
这真的很棒,但它有一个问题。每次格式化程序写入缓冲区时,它都会在撤消/重做历史记录中创建跳转。在尝试撤消/重做更改时会变得非常痛苦,因为每次第二次更改都是格式化程序(使光标跳转到第1行)。
所以我想知道,有没有办法在触发Fmt
后撤消撤消/重做历史记录的最新更改?
修改
好的,到目前为止我有:
au FileType go au BufWritePre <buffer> undojoin | Fmt
但它还不是很好。根据{{1}},撤消后不允许使用undojoin。当然,当我在撤消后尝试:h undojoin
时会触发错误。
那么我如何实现像这样的伪代码:
:w
如果我弄清楚最后一点,我想我有一个解决方案。
答案 0 :(得分:4)
我认为这几乎就在那里,完成了你的要求,但我看到它正在删除一个撤销点(我认为这是从undojoin
开始的):
function! GoFmt()
try
exe "undojoin"
exe "Fmt"
catch
endtry
endfunction
au FileType go au BufWritePre <buffer> call GoFmt()
根据MattyW的回答,我回忆起另一种选择:
au FileType go au BufWritePre <buffer> %!gofmt
:%!<some command>
在缓冲区上执行shell命令,所以我在将它写入文件之前执行。但是,它会把光标放在文件顶部......
答案 1 :(得分:2)
这是我的目标。它似乎与读/写autocmds和绑定到一个键都很好。它将光标放回原位 并且不包括undos中的文件顶部事件。
function! GoFormatBuffer()
if &modifiable == 1
let l:curw=winsaveview()
let l:tmpname=tempname()
call writefile(getline(1,'$'), l:tmpname)
call system("gofmt " . l:tmpname ." > /dev/null 2>&1")
if v:shell_error == 0
try | silent undojoin | catch | endtry
silent %!gofmt -tabwidth=4
endif
call delete(l:tmpname)
call winrestview(l:curw)
endif
endfunction
我检查是可修改的,因为我使用vim作为我的寻呼机。
答案 2 :(得分:1)
我在.vimrc中有这个:
au BufWritePost *.go !gofmt -w %
保存时自动在文件上运行gofmt。它实际上并没有在缓冲区中重新格式化,因此它不会中断我正在查看的内容,但它在磁盘上的格式正确,因此所有签入都已正确格式化。如果您希望看到格式正确的代码,您可以执行:e 。
对我的撤消/重做历史记录不做任何事情
答案 3 :(得分:1)
我尝试使用@ pepper_chino的答案,但遇到了问题,如果fmt错误然后vim将在运行GoFmt
之前撤消上一次更改。我以一种漫长且有点复杂的方式解决了这个问题:
" 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()
答案 4 :(得分:-3)