我想在没有安装任何插件的情况下在vim上运行gofmt。这就是我尝试过的(受https://gist.github.com/tbrisbout/a91ac3419440cde40c5f54dc32c94427启发):
function! GoFmt()
let file = expand('%')
silent execute "!gofmt -w " . file
edit!
endfunction
command! GoFmt call GoFmt()
augroup go_autocmd
autocmd BufWritePost *.go GoFmt
augroup END这只是在没有格式错误的情况下起作用。但是,如果代码包含错误,它会在屏幕底部显示错误消息,并且(看起来)它会以文本的形式出现在缓冲区中,因此整个代码就会中断。有什么简单的方法来处理vim上的这种工作吗?
发布于 2022-05-06 08:16:35
Gofmt既是一个代码格式化程序,也是一个linter,这是一个设计决策,使得它难以与Vim集成。在实践中,这意味着事情可以有三种方式:
例如,我们可以天真地尝试以gofmt的方式为gq和朋友使用:help 'formatprg',但是最终用垃圾的方式重写代码的可能性如下:
<standard input>:4:2: expected statement, found '.'
<standard input>:5:3: expected '}', found 'EOF'都太高了。就像在您的例子中,我们可以使用u来撤销,但这并不有趣。我想我们将不得不围绕gofmt糟糕的设计展开工作。
第一步:切换到:help BufWritePre。我们已经看到gofmt可以处理stdin,它允许我们格式化缓冲区以及文件。这很方便,因为写入文件后格式化文件是没有充分理由的第二次写入,并迫使我们在Vim…中重新加载它。而这一切似乎都是浪费。:help BufWritePost最好保存在不影响Vim状态的事情上。
function! GoFmt()
echomsg "hello"
endfunction
command! GoFmt call GoFmt()
augroup go_autocmd
autocmd BufWritePre *.go GoFmt
augroup END第二步:通过gofmt过滤整个缓冲区。
function! GoFmt()
silent %!gofmt
endfunction第三步:用基本撤销来“处理”最坏的情况。如果外部命令返回一个错误,我们可以通过:help v:shell_error获得它,并完成需要做的事情。
function! GoFmt()
silent %!gofmt
if v:shell_error > 0
silent undo
endif
endfunction第四步:尝试将光标保持在适当的位置。
function! GoFmt()
let saved_view = winsaveview()
silent %!gofmt
if v:shell_error > 0
silent undo
endif
call winrestview(saved_view)
endfunction见:help winsaveview()和:help winrestview()。
第五步:如果适用,创建一个包含gofmt报告错误的快速修复列表。:help getline()为我们提供了缓冲区的所有行-因此是所有的错误-在一个列表中,我们修改每个项目,以便文件名是当前的文件名,而不是无用的<standard input>。我们将该列表交给:help :cexpr,以便在取消筛选之前创建一个快速修复列表。
function! GoFmt()
let saved_view = winsaveview()
silent %!gofmt
if v:shell_error > 0
cexpr getline(1, '$')->map({ idx, val -> val->substitute('<standard input>', expand('%'), '') })
silent undo
endif
call winrestview(saved_view)
endfunction这一步有一点“绘制其余的*嚎叫”的感觉,但它实际上只是一个简单的:help substitute()在一个简单的:help map()。有关{ foo, bar -> baz }语法,请参见:help lambda。
第六步也是最后一步:如果存在任何有效错误,使用:help :cwindow打开quickfix窗口。
function! GoFmt()
let saved_view = winsaveview()
silent %!gofmt
if v:shell_error > 0
cexpr getline(1, '$')->map({ idx, val -> val->substitute('<standard input>', expand('%'), '') })
silent undo
cwindow
endif
call winrestview(saved_view)
endfunction

发布于 2022-05-06 15:19:55
您可以如下所示更新脚本:
function! GoFmt()
system('gofmt -e -w ' . expand('%'))
edit!
endfunctionGofmt是一个自动格式化Go源代码的工具。Gofmt既是一个代码格式化程序,也是一个linter。
来自文档
-e打印所有错误(包括虚假错误)。-w不将重新格式化的源打印到标准输出。如果文件的格式与gofmt不同,请用gofmt的版本覆盖它。如果在覆盖期间发生错误,则从自动备份还原原始文件。
如果没有错误,上面的脚本将更新文件。
如果适用,创建一个包含gofmt报告的错误的快速修复列表。
function! GoFmt()
cexpr system('gofmt -e -w ' . expand('%'))
edit!
endfunctioncexpr要创建一个快速修复列表,可以使用vim帮助文档help :cexpr读取有关它的更多信息,使用vim帮助文档help :system读取更多关于它的信息,expand展开通配符和特殊关键字到字符串中,使用vim帮助文档help :expand读取关于它的更多信息,%是引用当前文件的一个特殊关键字。
edit!用于重新加载文件内容。
然后,您可以使用quickfix快速跳过错误,您可以从这个blog帖子中了解更多有关它的信息。
https://stackoverflow.com/questions/72135274
复制相似问题