6

Go (Golang) 编程语言带有一个名为go fmt. 它是一个代码格式化程序,可自动格式化您的代码(对齐、字母排序、制表符、间距、成语......)。它真的很棒。

所以我发现了这个在 Vim 中使用它的小自动命令,每次缓冲区都保存到文件中。 au FileType go au BufWritePre <buffer> Fmt Fmt 是 Go vim 插件自带的功能。

这真的很棒,但它有1个问题。每次格式化程序写入缓冲区时,它都会在撤消/重做历史记录中创建一个跳转。当尝试撤消/重做更改时,这变得非常痛苦,因为每个第二次更改都是格式化程序(使光标跳转到第 1 行)。

所以我想知道,有没有办法在触发后丢弃撤消/重做历史中的最新更改Fmt

编辑: 好的,到目前为止我有: au FileType go au BufWritePre <buffer> undojoin | Fmt 但还不是很好。根据:h undojoin,撤消后不允许撤消加入。果然,当我尝试:w撤消后它会触发一个错误。

那么我该如何实现这样的伪代码:

if lastAction != undo then
    au FileType go au BufWritePre <buffer> undojoin | Fmt
end

如果我弄清楚了最后一点,我想我有一个解决方案。

4

5 回答 5

5

我认为这几乎就在那里,完成了你的要求,但我看到它正在删除一个撤消点(我认为这是预期的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 命令,所以我在将其写入文件之前执行此操作。而且,它会将光标放在文件顶部...

于 2013-08-30T15:19:43.253 回答
2

我尝试使用@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()
于 2014-02-21T09:25:22.523 回答
2

这是我的尝试。它似乎与读/写自动命令和绑定到一个键都很好。它将光标放回原处,并且在撤消中不包括文件顶部事件。

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

我检查 modifiable 因为我使用 vim 作为我的寻呼机。

于 2014-03-18T06:38:20.907 回答
1

我的 .vimrc 中只有这个:

au BufWritePost *.go !gofmt -w %

保存时自动在文件上运行 gofmt。它实际上并没有在缓冲区中重新格式化它,因此它不会中断我正在查看的内容,但它在磁盘上已正确格式化,因此所有签入都已正确格式化。如果您想查看格式正确的代码,您可以这样做:e

也不会对我的撤消/重做历史做任何事情

于 2013-08-30T16:40:49.660 回答
-2

您可以从默认存储库安装 vim 插件。或者,这里有一个病原体友好的镜子:

https://github.com/jnwhiteh/vim-golang

然后您可以使用 :Fmt 命令安全地执行 go fmt!

于 2013-08-30T19:41:51.883 回答