Awesome
nvim-go
A minimal implementation of Golang development plugin written in Lua for Neovim.
Introduction
Neovim (from v0.5) embeds a built-in Language Server Protocol (LSP) client. And Debug Adapter Protocol (DAP) are also brought into Neovim as a general debugger. With the power of them, we are able to easily turn Neovim into a powerful editor.
nvim-go
is designed to collaborate with them, provides sufficient features, and leverages community toolchains to get Golang development done.
Features
- Auto format with
:GoFormat
(viagoimports
,gofmt
,gofumpt
andlsp
) when saving. - Run linters with
:GoLint
(viarevive
) automatically. - Quickly test with
:GoTest
,:GoTestFunc
,:GoTestFile
and:GoTestAll
. Generate test with:GoAddTest
. - Import packages with
:GoGet
and:GoImport
. - Modify struct tags with
:GoAddTags
,:GoRemoveTags
,:GoClearTags
,:GoAddTagOptions
,:GoRemoveTagOptions
and:GoClearTagOptions
. - Generates JSON models with
:GoQuickType
(viaquicktype
). - Generate if err based on function return values with
:GoIfErr
(viaiferr
).
Recommended Features
This section can be regarded as a guide or common practice to develop with nvim-go
, LSP (gopls
) and DAP.
If you are familiar with these tools or other equivalent, you may skip this chapter.
Language Server
Language server provides vital language features to make Golang development easy.
We highly recommend you to use LSP client together with nvim-go
.
- Setup
gopls
with neovim/nvim-lspconfig. - Setup your favorite completion engine such as nvim-cmp.
- Setup and map the following methods based on what you need:
- Declaration:
vim.lsp.buf.declaration()
- Definition:
vim.lsp.buf.definition()
andvim.lsp.buf.type_definition()
- Implementation:
vim.lsp.buf.implementation()
- Hover:
vim.lsp.buf.hover()
- Signature:
vim.lsp.buf.signature_help()
- References:
vim.lsp.buf.reference()
- Symbols:
vim.lsp.buf.document_symbol()
andvim.lsp.buf.workspace_symbol()
- Rename:
vim.lsp.buf.rename()
- Format:
vim.lsp.buf.format()
, also works withGoFormat
. - Diagnostic:
vim.diagnostic
will also show lint issues with Virtual Text, which runsgo/analysis
. You may disableauto_lint
if this works well with your project.
For details of gopls
, please refer to https://github.com/golang/tools/blob/master/gopls/doc/design/design.md#features.
Debugger
</details>Installation
Prerequisites:
- Neovim (>= 0.7)
- npm (for quicktype)
Install with your favorite package manager:
" dependencies
use('nvim-lua/plenary.nvim')
" nvim-go
use('crispgm/nvim-go')
" (optional) if you enable nvim-notify
use('rcarriga/nvim-notify')
" (recommend) LSP config
use('neovim/nvim-lspconfig')
Finally, run :GoInstallBinaries
after plugin installed.
Install
quicktype
withyarn
orpnpm
:
nvim-go
install quicktype
with npm
by default, you may replace it with yarn
or pnpm
.
require('go').config.update_tool('quicktype', function(tool)
tool.pkg_mgr = 'yarn'
end)
Usage
Setup
-- setup nvim-go
require('go').setup({})
-- setup lsp client
require('lspconfig').gopls.setup({})
Defaults
require('go').setup({
-- notify: use nvim-notify
notify = false,
-- auto commands
auto_format = true,
auto_lint = true,
-- linters: revive, errcheck, staticcheck, golangci-lint
linter = 'revive',
-- linter_flags: e.g., {revive = {'-config', '/path/to/config.yml'}}
linter_flags = {},
-- lint_prompt_style: qf (quickfix), vt (virtual text)
lint_prompt_style = 'qf',
-- formatter: goimports, gofmt, gofumpt, lsp
formatter = 'goimports',
-- maintain cursor position after formatting loaded buffer
maintain_cursor_pos = false,
-- test flags: -count=1 will disable cache
test_flags = {'-v'},
test_timeout = '30s',
test_env = {},
-- show test result with popup window
test_popup = true,
test_popup_auto_leave = false,
test_popup_width = 80,
test_popup_height = 10,
-- test open
test_open_cmd = 'edit',
-- struct tags
tags_name = 'json',
tags_options = {'json=omitempty'},
tags_transform = 'snakecase',
tags_flags = {'-skip-unexported'},
-- quick type
quick_type_flags = {'--just-types'},
})
Manual
Display within Neovim with:
:help nvim-go
Advanced Configuration
Statusline Count
function! LintIssuesCount()
if exists('g:nvim_go#lint_issues_count')
return g:nvim_go#lint_issues_count
endif
endfunction
call airline#parts#define_function('nvim_go', 'LintIssuesCount')
call airline#parts#define_condition('nvim_go', '&filetype == "go"')
let g:airline_section_warning = airline#section#create_right(['nvim_go'])
function! LintIssuesCount()
if exists('g:nvim_go#lint_issues_count') && &filetype == 'go'
return g:nvim_go#lint_issues_count
endif
endfunction
let g:lightline = {
\ 'colorscheme': 'wombat',
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'readonly', 'filename', 'modified', 'lintcount' ] ]
\ },
\ 'component_function': {
\ 'lintcount': 'LintIssuesCount'
\ },
\ }
require('hardline').setup({
-- ...
sections = {
{
class = 'error',
item = function()
if
vim.bo.filetype == 'go'
and vim.g['nvim_go#lint_issues_count'] ~= nil
then
return vim.g['nvim_go#lint_issues_count']
else
return ''
end
end,
},
-- ...
}
Show Lint Issues without Focusing
augroup NvimGo
autocmd!
autocmd User NvimGoLintPopupPost wincmd p
augroup END
Or equivalently:
local NvimGo = vim.api.nvim_create_augroup("NvimGo", {
clear = true,
})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "NvimGoLintPopupPost",
group = NvimGo,
command = "wincmd p",
})