🗂

neovimのためのGoの開発環境のセットアップ

2021/01/16に公開

概要

neovim で Go の開発環境を構築するために必要な情報、セットアップ方法についてまとめます。
なお macOS 上で確認していますが、適宜自分の環境に置き換えてください。

必要なもの

  • 最新の neovim
  • neovim のプラグインマネージャー
  • 最新の Go
  • 最新の gopls

最新の neovim

GitHub リポジトリ
v0.5.0 以上の neovim からビルトインの LSP クライアントが使えます。
私は GitHub から curl で最新のリリースを落としてきて使っています。

$ cd
$ curl -LO https://github.com/neovim/neovim/releases/download/nightly/nvim-macos.tar.gz
$ tar xzf nvim-macos.tar.gz

PATH 環境変数に ~/nvim-macos/bin を入れておくとよいでしょう。

neovim のプラグインマネージャー

neovim 開発チームが提供している LSP クライアント設定を利用するためにプラグインマネージャーを使います。
私は dein.vim を使っていますが、vim-plug などもあります。
この記事では dein.vim を利用していることを想定します。

最新の Go

v1.15.5 が執筆時の最新バージョンです。
homebrew 経由で利用することが出来ます。

最新の gopls

ドキュメント
v0.6.2 が執筆時の最新のバージョンです。
インストールするには次のコマンドで最新のものをインストールします。

$ go get -u golang.org/x/tools/gopls@latest

手順

  1. 最新の gopls が動くようにする
  2. nvim の設定に LSP クライアントの設定を追加する
  3. 起動して動かしてみる

1. 最新の gopls が動くようにする

最新の gopls がそのプロジェクトで動くようにします。

2. nvim の設定に LSP クライアントの設定を追加する

公式ドキュメントの設定を参考に設定します。

基本の設定

nvim の LSP クライアントの設定は GitHub の neovim/nvim-lspconfig を使います。
このリポジトリを利用するとそれぞれの言語の LSP サーバーの起動設定を簡単に実行できます。
単に gopls を起動するだけなら次の設定を dein.vim に読み込ませる toml ファイルに記述すれば可能です。

[[plugins]]
repo = 'neovim/nvim-lspconfig'
hook_add = '''
lua << EOF
require'lspconfig'.gopls.setup{}
EOF
'''

ですが、これだけでは定義ジャンプも値参照も起動できないため、更に設定を追加していきます。

README にもあるサンプルの設定を元に次のように設定します。

lua << EOF
local nvim_lsp = require('lspconfig')
local on_attach = function(client, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end

  -- Mappings.
  local opts = { noremap=true, silent=true }
  buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
  buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
  buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
  buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
  buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
  buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
  buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
  buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
  buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
  buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
  buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
  buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)

  -- Set autocommands conditional on server_capabilities
  if client.resolved_capabilities.document_highlight then
    require('lspconfig').util.nvim_multiline_command [[
      :hi LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
      :hi LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
      :hi LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
      augroup lsp_document_highlight
        autocmd!
        autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
        autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
      augroup END
    ]]
  end
end
  nvim_lsp["gopls"].setup { on_attach = on_attach }
EOF

これで変数のリネームや、カーソル位置にある変数のドキュメントを見るなどの機能が利用できるようになりました。

コードフォーマットの設定

Go では書いたコードには gofmt もしくは goimports を実行し、フォーマットすることが求められます。
mattnさんの2020年1月のブログ記事でもあるように以前は LSP クライアントでは goimports を実行できませんでしたが、現在では公式ドキュメントで保存時に goimports を実行する方法が紹介されているます。
この設定をそのまま導入します。

補完の設定

私は deoplete.vimnvim-lua/completion-nvim などの補完プラグインを使っていません。
そのため neovim が提供している補完機能を使っています。

補完のための設定も公式ドキュメントにあるのでこちらを利用します。

デバッグモードで起動してみる

gopls がうまく動かない場合には gopls をデバッグモードで起動してみましょう。
デバッグモードで動かすためには gopls コマンドに -rpc.trace--debug=localhost:6060 をつけて実行します。
-rpc.trace フラグはより詳細な情報をログに出せるようにします。
--debug フラグは渡されたアドレスからデバッグのための情報を閲覧できるようにします。
nvim でこれらの設定を有効にするためには neovim/nvim-lspconfig のサーバーの起動コマンドを変更します。

lua << EOF
require('lspconfig').gopls.setup {
  cmd = {"gopls", "serve", "-rpc.trace", "--debug=localhost:6060"};
}
EOF

こうして neovim を起動し、 localhost:6060 にアクセスすると、詳細な情報を見ることが出来ます。

3. 起動してみる

ここまでの設定が出来たら実際に起動して、動作しているか遊んでみましょう。
なにか動かない設定があれば、デバッグモードで起動してどこでエラーが出ているのか調べて、 neovim のリポジトリの Issue にバグ報告や回避策がないか調べてみましょう。

最後に

2021/01/16 現在の neovim で gopls を使った開発環境について説明しました。
gopls の利用方法は公式ドキュメントがかなり充実しています。
この記事では説明しなかった daemon モードもドキュメントがあるので、読んでみると今後の gopls の成長について事前にわかるかもしれません。

Discussion