vim - 保存时自动格式化golang源代码

时间:2012-06-10 14:12:17

标签: go vim

我正在使用带有vim-golang插件的vim。这个插件附带a function called :Fmt,使用命令行可执行文件gofmt“重新格式化”源代码。

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

  1. 我找不到执行该功能的方法。我尝试在autocmd行的末尾写Fmt和:Fmt,但它似乎不起作用。我想我会想念一些东西,比如“打电话”。
  2. 我希望这只在保存文件类型'go'的文件时发生。我不知道如何结合这两个条件 - 我可以根据文件类型激活变量,我可以做一些小事情,比如删除尾随空格,保存文件时,但是分开。
  3. 所以这就是我到目前为止:

    " 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 个答案:

答案 0 :(得分:56)

缓冲区写入时不会触发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 ...(使用!)。

答案 1 :(得分: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 行中用 %!gofmt 替换 autocmd。这有利于向您显示 :w 上的语法错误。只要确保不要输入 :x:wq

答案 2 :(得分:1)

如果你使用折叠,gofmt将这些折叠起来(它打开封闭的折叠,关闭打开的折叠)。 要保持折叠,请使用以下自动命令

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

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