LazyVimでdenoとtsのlspを共存させる
はじめに
もともとtypescriptはよく使うのですが、個人的にdenoも触る機会が出てきました。
私は普段nvimでLazyVimを使っています。
となれば当然nvimでもdenoを書きたいのですが、lspがtsとかぶって快適なvimライフが送れなくなってしまいました。
これはいかんということでdenoとtsのlspをいい感じに共存させる設定をしました。
なかなかうまくいかなくてそれなりにプラグインのソースも読んだので、備忘録的にまとめておきます。

denoプロジェクトでvtslsも起動してしまう

普通のtsプロジェクトでdenolsも起動してしまう
関係するもの
- neovim 0.11.5
- LazyVim 15.13.0
- nvim-lspconfig 2.5.0
- mason-lspconfig 2.1.0
目標
目標というほどのものでもないですが、以下のような感じにしようと考えました。
- denoプロジェクトではdenoのlspを使う
- 普通のtsプロジェクトではtsのlspを使う
- denoプロジェクトと普通のtsプロジェクトの混在は想定しない
- denoとts以外(go とか)のlspは特に設定なしのデフォルトで動作する
設定だけ知りたい人へ
細かいことはいいから、設定だけ知りたい人向けにコードを載せておきます。
return {
{
"mason-org/mason-lspconfig.nvim",
version = "^2.0.0",
dependencies = {
{
"mason-org/mason.nvim",
---@module "mason"
---@type MasonSettings
opts = {},
},
{
"neovim/nvim-lspconfig",
---@module "lspconfig"
---@param opts PluginLspOpts
opts = function(_, opts)
local root_pattern = require("lspconfig.util").root_pattern
---@type table<string, lazyvim.lsp.Config|boolean>
local manual_setup_lsp = {
denols = {
mason = false,
root_dir = function(bufnr, on_dir)
local fname = vim.api.nvim_buf_get_name(bufnr)
local filepath = root_pattern("deno.json", "deno.jsonc")(fname)
if filepath == nil then
return
end
on_dir(root_pattern("deno.json", "deno.jsonc")(fname))
end,
},
vtsls = {
mason = false,
root_dir = function(bufnr, on_dir)
local fname = vim.api.nvim_buf_get_name(bufnr)
local deno_filepath = root_pattern("deno.json", "deno.jsonc")(fname)
-- deno.jsonがある場合は起動しない
if deno_filepath ~= nil then
return
end
on_dir(root_pattern("tsconfig.json", "package.json")(fname))
end,
},
}
local merged_config = vim.tbl_deep_extend("force", {}, opts.servers or {}, manual_setup_lsp or {})
opts.servers = merged_config
return opts
end,
},
},
config = function()
---@module "mason-lspconfig"
local mason_lspconfig = require("mason-lspconfig")
mason_lspconfig.setup({
automatic_enable = false,
ensure_installed = {
"denols",
"vtsls",
},
})
end,
},
}
mason-lspconfigの設定が効かない
もともと私はmasonを使ってlspを管理していました。
セットでmason-lspconfigも使ってlsp周りはよしなに起動してくれるようにしていました。
しかしこのmason-lspconfigがよろしくやってくれることが原因と考えました。
なので、mason_lspconfigでdenolsとvtsls(私はvtslsを使用してます)だけはmason-lspconfigの管轄外にして、手動で設定することにしました。
ドキュメントにもどうやらautomatic_enableを指定する方法が書いてあるのでこれやろ、と考えました。
しかし、これだけでは設定が反映されませんでした。
LazyVimがデフォルトでmason-lspconfigを呼んでた
調べてみると、LazyVimのlsp設定でmason-lspconfigを呼び出していることがわかりました。
挙動を見るとおそらくこの関係で、自身の設定で2回目のmason-lspconfigのセットアップが反映されていないようです。
ソース読む感じLazyVim側のmason-lspconfigだけを無効にはできなそうでした。
nvim-lspconfigでservers optionを上書きする
そういうことなので、nvim-lspconfigで設定を上書きすればよいのでは、と思いました。
opts callbackの引数にはLazyVim側のlspの設定が入ってくるので、そこにdenolsとvtslsの設定を追加するようにしました。
その結果が上記のコードになります。
余談ですが、nvim-lspconfigのソース読んでるとroot_dirの引数が2通りある気がしました。
--- 1
root_dir = function(fname)
--- 2
root_dir = function(bufnr, on_dir)
これってlspごとの仕様次第なんでしょうかね。知ってる方いたら教えていただけると嬉しいです。
まとめ
以上になります。
結果としては設定をおさえることになってしまいました。少ない設定で申し訳ありません。nvim0.11からlspはプラグインなしでも設定しやすくなっており、いっそ移行したい気持ちもあるので時間あるときにやってみようと思います。
次回は設定させていただきありがとうございますといえるようにしたいと思います。
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion