Neovim の LSP 関係のプラグインの役割
この記事は、vim 駅伝 2023/06/23 の記事です。
⠀
前回: 【企画】これだけは外せない!あなたにとっての「いぶし銀」な Vim プラグインを教えてください
次回: Denopsでプラグインを作るときのTips
自分が過去にかなり迷ったので、Neovim を本格的に使い始めたい、あるいは vim-lsp や coc.nvim から移行したい方へ残しておきます。
Neovim の builtin LSP の導入方法の記事を見たらインストールしておくべきプラグインの導入方法が書かれているのを見て、
結局、このプラグインって何のために入れてるの?
と思った方向けの記事のつもりです。
この記事では、以下の4つのプラグインについて扱います。
- nvim-lspconfig
- mason.nvim
- mason-lspconfig.nvim
- null-ls.nvim
builtin LSP について
現在の Neovim には、標準で LSP (Language Server Protocol) クライアントが備わっています。
これは、LS (Language Server) の起動・リクエストの送信や、レスポンスの処理などを簡単に行えるようにするためのものです。
この辺りの具体的な使い方は @ryoppippi さんの記事が分かりやすいと思います。
依存関係
今回扱うプラグインの中では
- mason-lspconfig.nvim の mason.nvim、nvim-lspconfig への依存
以外、依存関係はありません。
- nvim-lspconfig
- mason.nvim
- null-ls.nvim
これらの三つは別々に使うことができ、nvim-lspconfig、mason.nvim の両方を使っている場合にmason-lspconfig.nvim があったら簡単に設定ができる、というような関係です。
また、LSP を利用するプラグインも、mason.nvim、null-ls.nvim への依存はほぼないです。
nvim-lspconfig への依存は、特定の LS の機能強化のためのプラグイン(e.g. typescript.nvim、flutter-tools.nvim、...)でない限りしていないと思います。
プラグインの役割
nvim-lspconfig
「ほとんどの場合は、LSP の設定はこんな感じにするだろうな~」というものを集めたもの
シンプルに言うと設定集です。
ryoppippi さんの記事から引用させていただくと、builtint LSP の関数で lua-language-server を起動させたい場合、以下のように書くことができます。
vim.api.nvim_create_autocmd('FileType', {
pattern = 'lua',
callback = function()
vim.lsp.start({
name = 'lua_ls',
capabilities = vim.lsp.protocol.make_client_capabilities(),
cmd = { 'lua-language-server' },
root_dir = vim.fs.dirname(vim.fs.find({ '.git' }, { upward = true })[1]),
})
end,
})
vim.lsp.start()
の引数の中身を補足しておきます。
-
name
LSP 内部で使われる名前で、LS を識別するのに使われる。 -
capabilities
LS が提供する機能を示すもので、LS がどの機能を実装しているかを調べるときや、 LS に対して機能を指定するときなどに使われる。 -
cmd
LS を起動するコマンド、または RPC クライアントを返す関数。上の例だとlua-language-server
という名前のバイナリ、あるいは起動用のスクリプトに PATH が通っていれば起動できる。 -
root_dir
プロジェクトルート - ......
これらの値が vim.lsp.start_client()
に渡されて[1]起動します。
ただ、このままだと Git リポジトリしか root_dir
を正しく判定できませんし、場合によってはリポジトリルートとプロジェクトルートが異なっていたり、デフォルトの capabilities
を変更した方がよかったりと、一つの LS を追加するだけで多くの労力を要します。
nvim-lspconfig は、様々な LS のいい感じの設定を用意し、自分ですべてを設定するという手間を無くしてくれます。
require("lspconfig").lua_ls.setup({})
例えば、上記のような設定をした場合、以下の default_config
に色々処理を加えられたものが vim.lsp.start_client()
に渡されます。
mason.nvim
LS、debugger、formatter、linter とかのインストールを簡単にするもの
いわゆるパッケージマネージャです。
色々なツールを特定の箇所にダウンロード・インストールし、デフォルトでは PATH を通してくれます。
逆に言えば、元々インストールされているもの (e.g. deno、rustfmt、...) は、ここでインストールする必要はありません[2]。
また、下記のようなトラブルもたまにあるので、別の方法でインストールすることも視野に入れておくといいと思います。
mason-lspconfig.nvim
mason.nvim でインストールされている LS を、nvim-lspconfig で自動セットアップするもの
nvim-lspconfig を使用した場合、使用する LS それぞれに対して setup()
を呼ぶ必要があります。
local mason = require('mason')
local lspconfig = require('lspconfig')
mason.setup()
-- Lua_LS
lspconfig.lua_ls.setup({})
-- pyright
lspconfig.pyright.setup({})
-- vtsls
lspconfig.vtsls.setup({})
-- rust-analyzer
require('rust-tools').setup({})
......
また、設定された LS を見つけられなかった場合は警告を送ってくるので、 nvim-lspconfig 内部で使われている判定を通してから setup()
を呼ぶ、あるいは LS の追加・削除をするときに設定も編集する必要があり、面倒です。
そんな時に mason-lspconfig.nvim を使って以下のようにすることで、mason.nvim でインストールされている LS 全てを一括で処理することができます。
local mason = require('mason')
local lspconfig = require('lspconfig')
local mason_lspconfig = require('mason-lspconfig')
mason.setup()
mason_lspconfig.setup()
mason_lspconfig.setup_handlers({
function(server_name)
lspconfig[server_name].setup({})
end,
rust_analyzer = function() -- 個別に設定することもできる
require('rust-tools').setup({})
end,
......
})
また、
- mason.nvim と nvim-lspconfig で使用している LS の名前が異なっている場合の処理
- mason.nvim: lua-language-server
- nvim-lspconfig: lua_ls
- LS の自動インストール
も行ってくれます。
null-ls.nvim
LSP に対応していないツールを LS like に動かすもの
LSP には様々な機能が定義されていてます。
- エラー箇所の指摘
- コードのフォーマット
- 補完
- Code Action
- ......
しかし、LSP ではないものの、これらの機能を提供するツールもあります。formatter や linter がその最たる例でしょう。
例として clippy (Rust の linter) を挙げてみます。
このように、cargo clippy
を実行すると lint の結果が表示されます。しかし、この出力を直接 Neovim で使うことはできません。
これを解決するために、出力結果からデータを取得し、それを LS の機能として使えるようにするのが null-ls.nvim です。
波線が引かれている場所を Diagnostics として、修正案が書かれている部分を Code Action として提供することで、rust-analyzer (Rust の LS) の出した Diagnostics や Code Action と一緒に扱うことができます。
そうすることで、LSP というエコシステムを利用する他のプラグインと統合できたり、自分が設定の中で扱うのも容易になります。
その他
僕が使ってないので説明はできないものの、あると便利っぽいプラグインを紹介しておきます。
-
mason-null-ls.nvim
mason.nvim と null-ls.nvim を統合してくれる。 -
neoconf.nvim
VS Code の.vscode/settings.json
的なことができるようになる。
プロジェクトローカルな LS の設定とかもできる。
終わり
⠀
- documents -
Discussion