ITエンジニアによるITエンジニアのためのブログ

Neovim LSP

NeovimはLSP(Language Server Protocol)をサポートしており、LSPサーバーに対するクライアントとして使うことが可能です。LSPはコード補完、ホーバーによるドキュメンテーション表示、定義への移動などのコーディング支援機能を提供してくれます。

LSPプラグインとサーバーのインストール

一番単純なセットアップだと、インストールが必要なプラグインは”neovim/nvim-lspconfig”のみです。

まずはプラグインをPackerでインストールします。

~/.config/nvim/lua/user/plugins.lua

return packer.startup(function(use)
use "wbthomason/packer.nvim"
use "neovim/nvim-lspconfig"
end)

そして、lsp.luaファイルを作成し、以下のように記述します。

~/.config/nvim/lua/user/lsp.lua

-- Setup language servers.
local lspconfig = require('lspconfig')
lspconfig.solargraph.setup {}

ここではrubyのlspサーバーであるsolargraphを使うことにします。

solargraphはgemとしてインストールします。

gem install solargraph

~/.config/nvim/init.luaに以下のコードを記載し、lsp.luaを読み込みます。

require "user.lsp"

これで設定は完了です。

何かrubyファイルをNeovimで開くとLSPが使えるようになります。LSPクライアントがバッファにくっついているかを確認するには、コマンドラインモードで以下のコマンドを入力します。

:LspInfo

これでsolargraphがポップアップに表示されれば問題なく設定されています。

LSP用キーマップ

ただ、デフォルトの状態ではLSPのキーマップは設定されておらず、せっかくインストールしたLSPの機能のほとんどにアクセス出来ないので、lsp.luaにキーマップを追加します。ここではneovim/nvim-lspconfigのREADMEに例として記載されているキーマップをそのまま設定します。

~/.config/nvim/lua/user/lsp.lua

-- Global mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist)

-- Use LspAttach autocommand to only map the following keys
-- after the language server attaches to the current buffer
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('UserLspConfig', {}),
callback = function(ev)
-- Enable completion triggered by <c-x><c-o>
vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'

-- Buffer local mappings.
-- See `:help vim.lsp.*` for documentation on any of the below functions
local opts = { buffer = ev.buf }
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, opts)
vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, opts)
vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, opts)
vim.keymap.set('n', '<space>wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, opts)
vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, opts)
vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, opts)
vim.keymap.set({ 'n', 'v' }, '<space>ca', vim.lsp.buf.code_action, opts)
vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
vim.keymap.set('n', '<space>f', function()
vim.lsp.buf.format { async = true }
end, opts)
end,
})

これで、上記のキーマップを使ってLSPの機能にアクセス出来るようになります。それぞれの機能が何をするものなのかは、ぜひ実際に試したり、以下の例のようににヘルプのドキュメンテーションを確認してみてください。

:help vim.lsp.buf.hover()

LSPコード補完

キーマップで設定したように、このままでも挿入モードでCtrl-xとCtrl-oのシークエンスでコード補完を使うことが可能です。

ただ、もしバッファ補完などnvim-cmpプラグインの他の候補と一緒に表示したい場合は、LSP用のエクステンションプラグインの”hrsh7th/cmp-nvim-lsp”をインストールします。

~/.config/nvim/lua/user/plugins.lua

use "hrsh7th/cmp-nvim-lsp"

LSPをnvim-cmpのコード補完のソースに加えます。

~/.config/nvim/lua/user/cmp.lua

cmp.setup {
sources = {
{ name = 'nvim_lsp' }
}
}

そして、LSPサーバーのセットアップ時にcmp-nvim-lspのデフォルト設定を追加します。

-- Setup language servers.
local lspconfig = require('lspconfig')
local capabilities = require('cmp_nvim_lsp').default_capabilities()
lspconfig.solargraph.setup {
capabilities = capabilities,
}

これで、nvim-cmpのコード補完リストにLSPからの候補が表示されるようになります。

LSPを使うとコーディングが非常に快適になります。ここではruby用のサーバーを使って説明しましたが、ぜひご自身が使っている言語のLSPサーバーをインストールしてみてください。