Neovim Lua のための LuaLS セットアップ
はじめに
Neovim には Lua が組込まれており、設定ファイル (init.lua) やプラグインを Lua で書けます。
しかし Lua の言語機能はなかなか貧弱であり、LSP のサポートがないと体験は悪いです。
ですので sumneko 氏が開発しているこちらの Language server (以下 LuaLS
と表記) を入れている方は多いでしょう。
今回は LuaLS をちゃんと設定し、vim.api
やプラグインの補完などをバリバリ効くようにして快適にしていきます。
ターゲット
この記事の目的は LuaLS をいい感じに設定することだけです。
nvim-lspconfig や mason.nvim などには触れません。
参考元
公式のドキュメントはこちら。
型の付け方
LuaLS に型情報を伝えるには Annotations と呼ばれるコメント記法を使います。
ここを見てください。
設定方法
LuaLS の設定はここに一覧があります。
StyLua を使うから LuaLS の formatter は無効にしたい、だとか semantic highlight 要らないから切りたい、などの設定ができます。
そして今回の肝になるのは workspace.library
です。
lazy.nvim の場合
先にコードを載せます。
全てのプラグインを有効化する場合は以下のようにします。
ただし遅延起動を設定しており、このタイミングでまだ読み込まれていないプラグインは見つからないことに注意してください。
lspconfig.lua_ls.setup({
settings = {
Lua = {
runtime = {
version = "LuaJIT",
pathStrict = true,
path = { "?.lua", "?/init.lua" },
},
workspace = {
library = vim.list_extend(vim.api.nvim_get_runtime_file("lua", true), {
"${3rd}/luv/library",
"${3rd}/busted/library",
"${3rd}/luassert/library",
}),
checkThirdParty = "Disable",
},
},
},
})
一部のプラグインだけを有効化したい場合は以下のようにします。
get_plugin_paths()
はプラグインマネージャーによって実装が変わります。
筆者は lazy.nvim を使っています。
このようにプラグインマネージャーを経由すれば、遅延起動を設定しているプラグインであっても見つけられます。
local lspconfig = require("lspconfig")
---@param names string[]
---@return string[]
local function get_plugin_paths(names)
local plugins = require("lazy.core.config").plugins
local paths = {}
for _, name in ipairs(names) do
if plugins[name] then
table.insert(paths, plugins[name].dir .. "/lua")
else
vim.notify("Invalid plugin name: " .. name)
end
end
return paths
end
---@param plugins string[]
---@return string[]
local function library(plugins)
local paths = get_plugin_paths(plugins)
table.insert(paths, vim.fn.stdpath("config") .. "/lua")
table.insert(paths, vim.env.VIMRUNTIME .. "/lua")
table.insert(paths, "${3rd}/luv/library")
table.insert(paths, "${3rd}/busted/library")
table.insert(paths, "${3rd}/luassert/library")
return paths
end
lspconfig.lua_ls.setup({
settings = {
Lua = {
runtime = {
version = "LuaJIT",
pathStrict = true,
path = { "?.lua", "?/init.lua" },
},
workspace = {
library = library({ "lazy.nvim", "nvim-insx" }),
checkThirdParty = "Disable",
},
},
},
})
解説
workspace.library
はパスの配列で、ライブラリの場所を示します。
library()
関数は指定したプラグインのパスを検索し、更に Neovim や LuaLS の組込みライブラリへのパスを追加して返します。
LuaLS は workspace.library
の各ディレクトリに対して runtime.path
のパターンに一致するファイルを読み込みます。
このとき runtime.pathStrict
を設定しておかないと、ファジーに検索されるので上手くいかないことがあります。
例:
nvim-cmp
の場合lua/cmp/init.lua
とlua/cmp/types/cmp.lua
があり、require("cmp")
がどちらにもマッチしてしまうのでlibrary.path
の順序からlua/cmp/types/cmp.lua
が優先されてしまいます。
これを回避するため runtime.pathStrict
を有効化し、プラグインのルートに /lua
を追加したパスを返すようにします。
vim.fn.stdpath("config")
はユーザーの設定ファイルの配置場所です。
自分で定義した便利関数などの補完が効くようになります。
vim.env.VIMRUNTIME
は doc/
や ftplugin/
などがインストールされたパスです。
これを追加することで vim.fn.*
や vim.api.*
などの補完が効くようになります。
${3rd}
は LuaLS 組込みのライブラリへのパスに展開されます。
busted
や luassert
はテスト用のライブラリなので init.lua
を書くだけなら不要かと思います。
プラグイン開発者向けの設定です。
luv
は vim.uv
(旧 vim.loop
) なので、入れておいた方が便利かと思います。
ただ、これは将来的に削除されるらしいです。
終わり
快適な Lua ライフを!
Discussion