首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在没有插件的vim上运行gofmt

在没有插件的vim上运行gofmt
EN

Stack Overflow用户
提问于 2022-05-06 01:38:46
回答 2查看 678关注 0票数 3

我想在没有安装任何插件的情况下在vim上运行gofmt。这就是我尝试过的(受https://gist.github.com/tbrisbout/a91ac3419440cde40c5f54dc32c94427启发):

代码语言:javascript
复制
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上的这种工作吗?

EN

回答 2

Stack Overflow用户

发布于 2022-05-06 08:16:35

Gofmt既是一个代码格式化程序,也是一个linter,这是一个设计决策,使得它难以与Vim集成。在实践中,这意味着事情可以有三种方式:

  • 你的代码很完美,什么都没发生,
  • 您的代码存在格式化问题,需要重新格式化,
  • 您的代码有语法问题,输出错误列表。

例如,我们可以天真地尝试以gofmt的方式为gq和朋友使用:help 'formatprg',但是最终用垃圾的方式重写代码的可能性如下:

代码语言:javascript
复制
<standard input>:4:2: expected statement, found '.'
<standard input>:5:3: expected '}', found 'EOF'

都太高了。就像在您的例子中,我们可以使用u来撤销,但这并不有趣。我想我们将不得不围绕gofmt糟糕的设计展开工作。

第一步:切换到:help BufWritePre。我们已经看到gofmt可以处理stdin,它允许我们格式化缓冲区以及文件。这很方便,因为写入文件后格式化文件是没有充分理由的第二次写入,并迫使我们在Vim…中重新加载它。而这一切似乎都是浪费。:help BufWritePost最好保存在不影响Vim状态的事情上。

代码语言:javascript
复制
function! GoFmt()
  echomsg "hello"
endfunction

command! GoFmt call GoFmt()

augroup go_autocmd
  autocmd BufWritePre *.go GoFmt
augroup END

第二步:通过gofmt过滤整个缓冲区。

代码语言:javascript
复制
function! GoFmt()
  silent %!gofmt
endfunction
  • 最好的情况是:什么也不发生,或者缓冲区被格式化的内容覆盖。
  • 最坏的情况是:整个缓冲区被错误报告替换。

第三步:用基本撤销来“处理”最坏的情况。如果外部命令返回一个错误,我们可以通过:help v:shell_error获得它,并完成需要做的事情。

代码语言:javascript
复制
function! GoFmt()
  silent %!gofmt
  if v:shell_error > 0
    silent undo
  endif
endfunction

第四步:尝试将光标保持在适当的位置。

代码语言:javascript
复制
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,以便在取消筛选之前创建一个快速修复列表。

代码语言:javascript
复制
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窗口。

代码语言:javascript
复制
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

票数 4
EN

Stack Overflow用户

发布于 2022-05-06 15:19:55

您可以如下所示更新脚本:

代码语言:javascript
复制
function! GoFmt()
  system('gofmt -e -w ' . expand('%'))
  edit!
endfunction

Gofmt是一个自动格式化Go源代码的工具。Gofmt既是一个代码格式化程序,也是一个linter。

来自文档

-e打印所有错误(包括虚假错误)。-w不将重新格式化的源打印到标准输出。如果文件的格式与gofmt不同,请用gofmt的版本覆盖它。如果在覆盖期间发生错误,则从自动备份还原原始文件。

如果没有错误,上面的脚本将更新文件。

如果适用,创建一个包含gofmt报告的错误的快速修复列表。

代码语言:javascript
复制
function! GoFmt()
  cexpr system('gofmt -e -w ' . expand('%'))
  edit!
endfunction

cexpr要创建一个快速修复列表,可以使用vim帮助文档help :cexpr读取有关它的更多信息,使用vim帮助文档help :system读取更多关于它的信息,expand展开通配符和特殊关键字到字符串中,使用vim帮助文档help :expand读取关于它的更多信息,%是引用当前文件的一个特殊关键字。

edit!用于重新加载文件内容。

然后,您可以使用quickfix快速跳过错误,您可以从这个blog帖子中了解更多有关它的信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72135274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档