27

我正在使用 vim 和vim-golang插件。这个插件带有一个名为 : Fmt 的函数,它使用gofmt(一个命令行可执行文件)“重新格式化”源代码。

我想在每次保存文件时调用 :Fmt 函数,因此它会不断重新格式化。我认为这应该使用autocmd指令来完成。但我有两个疑问:

  1. 我找不到执行该功能的方法。我尝试在 autocmd 行的末尾写 Fmt 和 :Fmt ,但它似乎没有用。我想我错过了一些东西,比如“通话”。
  2. 我希望仅在保存文件类型为“go”的文件时才发生这种情况。我不知道如何结合这两个条件 - 我可以根据文件类型激活变量,并且我可以做一些小事情,比如在保存文件时删除尾随空格,但要分开保存。

所以这就是我到目前为止所拥有的:

" I can set variables for go like this
autocmd FileType go setlocal noexpandtab shiftwidth=4 tabstop=4 softtabstop=4 nolist

" I can clean trailing spaces(conserving cursor position) on save like this
autocmd BufWritePre * kz|:%s/\s\+$//e|'z

" None of these worked:
autocmd BufWritePre,FileType go Fmt
autocmd BufWritePre,FileType go :Fmt
4

3 回答 3

61

FileType事件不会在缓冲区写入时触发;BufWritePre是正确的,但您需要提供文件模式,例如*.go

autocmd BufWritePre *.go Fmt

唯一的缺点是这重复了go文件类型的检测。您可以通过挂钩事件来委托它FileType,然后使用特殊<buffer>模式为每个 Go 缓冲区定义格式化 autocmd:

autocmd FileType go autocmd BufWritePre <buffer> Fmt

这样做的缺点是,如果文件类型被多次设置,您也将多次运行格式化。这可以通过 custom 来解决:augroup,但现在它变得非常复杂。或者,如果您确实确定这是BufWritePreGo 缓冲区的唯一自动命令,您可以使用:autocmd! BufWritePre ...(with a !)。

于 2012-06-10T14:38:48.470 回答
2

如果你使用折叠,gofmt 会把这些弄乱(它打开闭合的折叠,关闭打开的折叠)。要保持折叠状态,请使用以下自动命令

autocmd FileType go autocmd BufWritePre <buffer> execute "normal! mz:mkview\<esc>:Fmt\<esc>:loadview\<esc>`z"

它使用 z 寄存器来标记光标位置,因为 :mkview 和 :loadview (保存并恢复折叠)出于某种原因移动光标。

于 2013-04-11T20:44:44.760 回答
2

For those not using the plugin, this should work:

autocmd FileType go autocmd BufWritePre <buffer> execute "normal! mz:mkview\<esc>:%!gofmt-safe\<esc>:loadview\<esc>`z"

Add the following script to your PATH, this is needed otherwise gofmt will nuke the file if there are any syntax errors. This can be dangerous if you type :x for instance.

gofmt-safe

#!/usr/bin/env bash

orig=$(mktemp)
fmt=$(mktemp)

cat > "$orig"

<"$orig" gofmt "$@" > "$fmt" 2>/dev/null

if [ $? -eq 0 ]; then
    cat "$fmt"
else
    cat "$orig"
fi

rm -f "$orig" "$fmt"

If you want live dangerously without this script, you can replace %!gofmt-safe with %!gofmt in the autocmd line. This has the benefit of showing you syntax errors on :w. Just make sure not to type :x or :wq.

于 2020-12-21T20:37:09.220 回答