当保存时自动格式化Golang源代码的vim设置

29
我正在使用vim-golang插件的vim。该插件带有一个名为:Fmt的函数,使用命令行可执行文件gofmt对源代码进行“重新格式化”。
我想每次保存文件时调用:Fmt函数,以便持续重新格式化。我认为应该使用autocmd指令来完成此操作。但是我有两个疑问:
  1. 我找不到执行该函数的方法。我尝试在autocmd行的末尾编写Fmt和:Fmt,但似乎没有起作用。我认为我漏掉了某些东西,比如“call”。
  2. 我希望只在保存filetype为'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
3个回答

61

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

autocmd BufWritePre *.go Fmt

唯一的缺点是这会重复检测 go 文件类型。你可以通过钩子函数 FileType 代理此操作,然后使用特殊的 <buffer> 模式为每个Go缓冲区定义格式化autocmd:

autocmd FileType go autocmd BufWritePre <buffer> Fmt

这种方法的缺点是,如果文件类型设置多次,你也会运行多次格式化。可以通过自定义 :augroup 来解决,但这样会变得非常复杂。或者,如果你确信这是 Go 缓冲区的唯一 BufWritePre autocmd,那么可以使用 :autocmd! BufWritePre ...(加上 !)。


哇,非常详尽的回答,非常感谢!我最终采用了第二个选项 - 我不打算重置文件类型。谢谢! - kikito
1
如果您需要从 Fmt 命令中获得正常输出(我一直看到 X 行已过滤),则可能需要添加 silentautocmd FileType go autocmd BufWritePre silent Fmt - djd
1
它已经在 vim-gocode 插件中了 https://github.com/Blackrush/vim-gocode/blob/master/ftplugin/go/fmt.vim#L20 - Anton Egorov
场景是在登机口编码。如果代码出现错误,我仍然需要保存文件怎么办?在我的情况下,它不允许我保存文件。有没有一种方法可以强制保存这样的文件? - Igor Gatis
1
PS!从Go 1.4(其中misc/vim被删除)开始,您必须安装https://github.com/vim-jp/vim-go-extra才能使@IngoKarkat的说明起作用。或者,在Go GitHub wiki上浏览其他选项。 - Sindre Myren
显示剩余2条评论

2

对于那些没有使用插件的人,可以尝试以下方法:

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

将以下脚本添加到您的PATH中,否则如果有任何语法错误,gofmt将会删除文件。如果您输入:x等命令,则可能很危险。 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"

如果您想在不使用此脚本的情况下冒险,可以将 %!gofmt-safe 替换为 %!gofmtautocmd 行中。这样做的好处是在 :w 时显示语法错误。只需确保不要键入 :x:wq


2
如果您使用折叠功能,gofmt会破坏这些折叠(它会打开关闭的折叠,关闭打开的折叠)。 为了保持折叠的原样,请使用以下自动命令。
autocmd FileType go autocmd BufWritePre <buffer> execute "normal! mz:mkview\<esc>:Fmt\<esc>:loadview\<esc>`z"

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接