## 背景
[[Neovim]] 0.11がリリースされて、nativeの[[LSP]]機能がかなり強化された。そのうちの1つにセットアップや設定がかなりシンプルになったというものがある。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://gpanders.com/favicon-32x32.png" />
<span class="link-card-v2-site-name">gpanders.com</span>
</div>
<div class="link-card-v2-title">
What's New in Neovim 0.11 | g.p. anders
</div>
<div class="link-card-v2-content">
Neovim 0.11 was just released. As in previous installments in this series, let’s talk a bit about some of the bi ...
</div>
<a href="https://gpanders.com/blog/whats-new-in-neovim-0-11/#simpler-lsp-setup-and-configuration"></a>
</div>
[[nvim-lspconfig]]もこの流れに従い、v2から[[Neovim]]のv0.10以下とv0.11以上で異なるセットアップ方式が案内されるようになっていた。今後のことも考えて、新しい設定方式に移行する。
## 環境
| 対象 | バージョン |
| ------------------ | ----------- |
| [[Ubuntu]] | 24.04.1 LTS |
| [[Neovim]] | v0.11.0 |
| [[nvim-lspconfig]] | `2e74354` |
## 変更点把握
### LSPの有効はlsp.enableになる
```diff
- lspconfig.golangci_lint_ls.setup({})
+ vim.lsp.enable("golangci_lint")
```
のようになるらしい。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
GitHub - neovim/nvim-lspconfig: Quickstart configs for Nvim LSP
</div>
<div class="link-card-v2-content">
Quickstart configs for Nvim LSP. Contribute to neovim/nvim-lspconfig development by creating an account on GitHu ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/6d30df0a9813edc0573ba51733be995d71311b5251b39cc663cb436b4487eb5c/neovim/nvim-lspconfig" />
<a href="https://github.com/neovim/nvim-lspconfig?tab=readme-ov-file#quickstart"></a>
</div>
### LSPの設定はlsp.configになる
```lua
local lspconfig = require('lspconfig')
lspconfig.gopls.setup({
settings = {
gopls = {
gofumpt = true,
},
},
})
```
は
```lua
vim.lsp.config("gopls", {
settings = {
gopls = {
gofumpt = true,
},
},
}
```
のようになるらしい。`lspconfig` のrequireが不要になるが、設定の中身はそのまま。シンプルでよい。今までは `setup` で設定と有効を同時にやっていたが、今後は別になる点が注意。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
GitHub - neovim/nvim-lspconfig: Quickstart configs for Nvim LSP
</div>
<div class="link-card-v2-content">
Quickstart configs for Nvim LSP. Contribute to neovim/nvim-lspconfig development by creating an account on GitHu ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/6d30df0a9813edc0573ba51733be995d71311b5251b39cc663cb436b4487eb5c/neovim/nvim-lspconfig" />
<a href="https://github.com/neovim/nvim-lspconfig?tab=readme-ov-file#configuration"></a>
</div>
### lspディレクトリに設定を分離する
[[Neovim]] 0.11からは `lsp` ディレクトリ配下に各LSP設定を分離できるようになった。
> When an LSP client starts, it resolves its configuration by merging from the following (in increasing priority):
>
> 1. Configuration defined for the '\*' name.
> 2. Configuration from the result of merging all tables returned by lsp/\<name\>.lua files in 'runtimepath' for a server of name name.
> 3. Configurations defined anywhere else.
>
> *[Lsp \- Neovim docs](https://neovim.io/doc/user/lsp.html#lsp-config)*
この優先度を日本語にすると以下のようになる。
1. `*` で指定された設定
2. runtimepath 配下の `lsp/<name>.lua` に記載された設定
3. それ以外で定義した設定
以上から以下のような設定をとればよさそう。
1. 共通な設定は `vim.lsp.config("*", { ... })` でしておく
2. それ以外の設定は `lsp/<name>.lua` に書いておく
この設定を使うことで、先ほど [[#LSPの設定はlsp.configになる]] で提示したコードは更にシンプルになる。
```diff
- vim.lsp.config("gopls", {
+ return {
settings = {
gopls = {
gofumpt = true,
},
},
}
```
#### lsp配下に未対応なLSP
一部のconfigは `lsp/<name>.lua` 形式に対応されていない。以下のissueを参照。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
Missing legacy configs · Issue #3705 · neovim/nvim-lspconfig
</div>
<div class="link-card-v2-content">
These legacy configs may require onnewconfig, so aren't migrated to the new lsp/*.lua format: angularls apexls a ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/c2391fc8764a7923076e2e7365c2fc24cdca31241e00ae2df3de9db46f4889de/neovim/nvim-lspconfig/issues/3705" />
<a href="https://github.com/neovim/nvim-lspconfig/issues/3705"></a>
</div>
自分が使っているものもいくつかあった。
- eslint
- tailwindcss
- volar
- biome
ただ、いずれもv2.1.0で対応されていたので問題はなさそう。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
Release v2.1.0 · neovim/nvim-lspconfig
</div>
<div class="link-card-v2-content">
What's ChangedNeovim 0.11 migration by @TheRealLorenz in #3659feat(typos-lsp): support pyproject.toml and Cargo. ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/fb948d5376d02569b50be95a078a76a11f567303aea9b10f7c298c7c405f5ecb/neovim/nvim-lspconfig/releases/tag/v2.1.0" />
<a href="https://github.com/neovim/nvim-lspconfig/releases/tag/v2.1.0"></a>
</div>
## capabilities
[[blink.cmp (Neovim)|blink.cmp]]や[[nvim-ufo]]といった補完に関するプラグインを使っているため、現状ではcapabilitiesを作成して、すべての[[LSP]]設定に割り当てている。これをどうすべきか。
```lua
local capabilities = require("blink.cmp").get_lsp_capabilities({
textDocument = {
completion = {
completionItem = {
snippetSupport = true,
},
},
foldingRange = {
dynamicRegistration = false,
lineFoldingOnly = true,
},
},
})
lspconfig.ruff.setup({
capabilities = capabilities,
```
### blink.cmp
[[blink.cmp (Neovim)|blink.cmp]]の場合、以下で言及された記述をクリアできれば capabilities の指定は不要。該当issueはclosedされているので問題ないはず。
> WARNING
>
> On Neovim 0.11+ with vim.lsp.config, you may skip this step. This is still required when using nvim-lspconfig until [this issue is completed](https://github.com/neovim/nvim-lspconfig/issues/3494)
>
> *[Installation \| Blink Completion \(blink\.cmp\)](https://cmp.saghen.dev/installation.html#lsp-capabilities)*
### nvim-ufo
[[nvim-ufo]]の場合は、デフォルト設定と異なるため `textDocument.foldingRange` の指定は必要そう。
> ```lua
> -- Option 2: nvim lsp as LSP client
> -- Tell the server the capability of foldingRange,
> -- Neovim hasn't added foldingRange to default capabilities, users must add it manually
> local capabilities = vim.lsp.protocol.make_client_capabilities()
> capabilities.textDocument.foldingRange = {
> dynamicRegistration = false,
> lineFoldingOnly = true
> }
> ```
> *[kevinhwang91/nvim\-ufo: Not UFO in the sky, but an ultra fold in Neovim\.](https://github.com/kevinhwang91/nvim-ufo?tab=readme-ov-file#minimal-configuration)*
### capabilitiesの指定方法
これは一括しての設定なので、[[#lspディレクトリに設定を分離する]] の2に記載した `vim.lsp.config("*", { ... })` を使えばよい。
現状はこうなっているが
```lua
local capabilities = require("blink.cmp").get_lsp_capabilities({
textDocument = {
-- これはnvim-cmpの名残かも?
completion = {
completionItem = {
snippetSupport = true,
},
},
-- nvim-ufoの設定
foldingRange = {
dynamicRegistration = false,
lineFoldingOnly = true,
},
},
})
```
こんな感じになるはず。
```lua
vim.lsp.config("*", {
capabilities = {
textDocument = {
foldingRange = {
dynamicRegistration = false,
lineFoldingOnly = true,
},
},
}
})
```
capabilities が上書きされないか少し不安だったので [[DeepWiki]] に聞いてみた。大丈夫そう。(しかし神すぎるなこのツール...)
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://deepwiki.com/favicon.ico" />
<span class="link-card-v2-site-name">deepwiki.com</span>
</div>
<div class="link-card-v2-title">
DeepWiki
</div>
<div class="link-card-v2-content">
Which repo would you like to understand?
</div>
<a href="https://deepwiki.com/search/local-capabilities-requireblin_610e358c-1207-4271-8ef6-0cfe7923621f"></a>
</div>
## 設定変更
実際に設定変更してみる。結局必要な作業は以下。
- `nvim/lsp` 配下に `<name>.lua` を作成
- `nvim-lspconfig.lua` から `config` を削除する
## トラブル
### setupエラー
`biome.json` を開いてみたらエラーに。
```error
Failed to run `config` for nvim-lspconfig
...local/share/nvim/lazy/lazy.nvim/lua/lazy/core/loader.lua:387: attempt to call field 'setup' (a table value)
# stacktrace:
- vim/_editor.lua:0 _in_ **cmd**
- /snacks.nvim/lua/snacks/picker/actions.lua:115 _in_ **jump**
- /snacks.nvim/lua/snacks/picker/actions.lua:36
```
`vim.lsp.enable` をしていなかった...。ただ、[[nvim-lspconfig]]の `config` で設定してしまうと、すべての[[LSP]]が有効になってしまう... と思ったが、どうやら `vim.lsp.enable` だけでは有効にならないらしい。必要なときに[[LSP]]がアタッチされるための設定をするだけっぽい。
### nvim-lspconfigの設定を上書きできない
以下で調査、対応。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
📝nvim-lspconfigでruntimepath配下のluaディレクトリ配下に配置したLSP設定が読み込まれない
</div>
<div class="link-card-v2-content">Neovim 0.11環境でnvim-lspconfigのLSP設定がruntimepath配下のlua/lspディレクトリから読み込まれず、root_markersが上書きされる問題の原因はruntimepathの順序である。解決策は~/.config/nvim/after/luaへ移動することである。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/troubleshooting.webp" />
<a data-href="📝nvim-lspconfigでruntimepath配下のluaディレクトリ配下に配置したLSP設定が読み込まれない" class="internal-link"></a>
</div>
%%[[📝nvim-lspconfigでruntimepath配下のluaディレクトリ配下に配置したLSP設定が読み込まれない]]%%
### 期待していないLSPが有効になってしまう
[[ESLint]]が入っていないプロジェクトで[[ESLint]]の[[LSP]]から警告が出てしまう。
```warning
[lspconfig] Unable to find ESLint library.
```
`Root directory` は `nil`
```
- eslint (id: 4)
- Version: ? (no serverInfo.version response)
- Root directory: nil
```
[[Deno]]プロジェクトじゃないので `denols` も本来はactivateしてほしくない。
```
- denols (id: 1)
- Version: 2.2.3 (release, x86_64-unknown-linux-gnu)
- Root directory: nil
```
[[Neovim]] v0.11.1 にバージョンアップし、[[workspace_required (Neovim)|workspace_required]]に `true` を指定することで[[特定ファイルが存在する場合だけLSPを有効化 (nvim-lspconfig)|特定ファイルが存在する場合だけLSPを有効化]]する。
`nvim/after/lsp/denols.lua`
```lua
return {
workspace_required = true,
}
```
[[root_markers (Neovim)|root_markers]]や[[root_dir (Neovim)|root_dir]]は基本的にいい感じになっているので、特に変更しなくても平気だった。
## 参考
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://static.zenn.studio/images/logo-transparent.png" />
<span class="link-card-v2-site-name">Zenn</span>
</div>
<div class="link-card-v2-title">
忙しい人向け nvim-lspconfigのnvim v0.11対応
</div>
<img class="link-card-v2-image" src="https://res.cloudinary.com/zenn/image/upload/s--caxEvMqp--/c_fit%2Cg_north_west%2Cl_text:notosansjp-medium.otf_55:%25E5%25BF%2599%25E3%2581%2597%25E3%2581%2584%25E4%25BA%25BA%25E5%2590%2591%25E3%2581%2591%2520nvim-lspconfig%25E3%2581%25AEnvim%2520v0.11%25E5%25AF%25BE%25E5%25BF%259C%2Cw_1010%2Cx_90%2Cy_100/g_south_west%2Cl_text:notosansjp-medium.otf_34:yuys13%2Cx_220%2Cy_108/bo_3px_solid_rgb:d6e3ed%2Cg_south_west%2Ch_90%2Cl_fetch:aHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL3plbm4tdXNlci11cGxvYWQvYXZhdGFyLzU1YzllYzNiYzAuanBlZw==%2Cr_20%2Cw_90%2Cx_92%2Cy_102/co_rgb:6e7b85%2Cg_south_west%2Cl_text:notosansjp-medium.otf_30:vim-jp%2Cx_220%2Cy_160/bo_4px_solid_white%2Cg_south_west%2Ch_50%2Cl_fetch:aHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EvQUNnOG9jSkdUVzdxTlZFNU5zWlc1OUFiQk4yQlpkRUVLX2lmbnRPU2tjbGJhQ3p6V0xyTG5NWU89czk2LWM=%2Cr_max%2Cw_50%2Cx_139%2Cy_84/v1627283836/default/og-base-w1200-v2.png" />
<a href="https://zenn.dev/vim_jp/articles/migrate-nvim-lspconfig-v0_11"></a>
</div>
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://static.zenn.studio/images/logo-transparent.png" />
<span class="link-card-v2-site-name">Zenn</span>
</div>
<div class="link-card-v2-title">
Neovim0.11用のLSP設定
</div>
<img class="link-card-v2-image" src="https://res.cloudinary.com/zenn/image/upload/s--cMNw-wyT--/c_fit%2Cg_north_west%2Cl_text:notosansjp-medium.otf_66:Neovim0.11%25E7%2594%25A8%25E3%2581%25AELSP%25E8%25A8%25AD%25E5%25AE%259A%2Cw_1010%2Cx_90%2Cy_100/g_south_west%2Cl_text:notosansjp-medium.otf_37:kawarimidoll%2Cx_203%2Cy_121/g_south_west%2Ch_90%2Cl_fetch:aHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL3plbm4tdXNlci11cGxvYWQvYXZhdGFyLzIzNzlhYzhkODYuanBlZw==%2Cr_max%2Cw_90%2Cx_87%2Cy_95/v1627283836/default/og-base-w1200-v2.png" />
<a href="https://zenn.dev/kawarimidoll/articles/b202e546bca344"></a>
</div>