Skip to content

A minimal implementation of Golang development plugin for Neovim

License

Notifications You must be signed in to change notification settings

crispgm/nvim-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nvim-go

build

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 (via goimports, gofmt, gofumpt and lsp) when saving.
  • Run linters with :GoLint (via revive) 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 (via quicktype).
  • Generate if err based on function return values with :GoIfErr (via iferr).

Screenshots

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.

<Show/Hide the guide>

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.

  1. Setup gopls with neovim/nvim-lspconfig.
  2. Setup your favorite completion engine such as nvim-cmp.
  3. Setup and map the following methods based on what you need:
  • Declaration: vim.lsp.buf.declaration()
  • Definition: vim.lsp.buf.definition() and vim.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() and vim.lsp.buf.workspace_symbol()
  • Rename: vim.lsp.buf.rename()
  • Format: vim.lsp.buf.format(), also works with GoFormat.
  • Diagnostic: vim.diagnostic will also show lint issues with Virtual Text, which runs go/analysis. You may disable auto_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

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 with yarn or pnpm:

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

vim-airline:

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'])

lightline:

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'
  \ },
  \ }

nvim-hardline:

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",
})

License

MIT