はじめに
coc.nvim
を使うのがベストな選択肢でしたが、neovim builtin lsp(以下 nvim-lsp)でもかなりエコシステムが整備されており、VSCode 並の開発体験が得られるようになっています。この記事ではそんな nvim-lsp の設定の基本的なところを説明します。環境
- Windows でも MacOS でも Linux でも動くはずです。
- Neovim stable 最新版もしくは nightly
- git コマンド
- その他 Mason から色々な物をインストールして使う際には
checkhealth mason
で指定されたコマンドが必要となることがあります。
基本的な設定
必須プラグイン系
- nvim-lspconfig (https://github.com/neovim/nvim-lspconfig)
- mason.nvim (https://github.com/williamboman/mason.nvim)
- mason-lspconfig.nvim (https://github.com/williamboman/mason-lspconfig.nvim)
package.json
がある場合は Typescript の言語サーバーが起動してほしいなど)はそれぞれ違うのでこのプラグインが必要になります。local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system {
"git",
"clone",
"--filter=blob:none",
"--single-branch",
"https://github.com/folke/lazy.nvim.git",
lazypath,
}
end
vim.opt.runtimepath:prepend(lazypath)
require("lazy").setup({
{
"neovim/nvim-lspconfig",
cmd = { "LspInfo", "LspLog" },
event = { "BufRead" },
config = function()
require "user.config.lsp.setup"
end,
},
{
"williamboman/mason.nvim",
cmd = { "Mason", "MasonInstall" },
event = { "WinNew", "WinLeave", "BufRead" },
config = function()
require "user.config.mason"
end,
},
{ "williamboman/mason-lspconfig.nvim" },
}, {})
local on_attach = function(client, bufnr)
-- LSPサーバーのフォーマット機能を無効にするには下の行をコメントアウト
-- 例えばtypescript-language-serverにはコードのフォーマット機能が付いているが代わりにprettierでフォーマットしたいときなど
-- client.resolved_capabilities.document_formatting = false
local set = vim.keymap.set
set("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>")
set("n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>")
set("n", "K", "<cmd>lua vim.lsp.buf.hover()<CR>")
set("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>")
set("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>")
set("n", "<space>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>")
set("n", "<space>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>")
set("n", "<space>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>")
set("n", "<space>D", "<cmd>lua vim.lsp.buf.type_definition()<CR>")
set("n", "<space>rn", "<cmd>lua vim.lsp.buf.rename()<CR>")
set("n", "<space>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>")
set("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>")
set("n", "<space>e", "<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>")
set("n", "[d", "<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>")
set("n", "]d", "<cmd>lua vim.lsp.diagnostic.goto_next()<CR>")
set("n", "<space>q", "<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>")
set("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>")
end
require("mason").setup()
require("mason-lspconfig").setup()
require("mason-lspconfig").setup_handlers {
function (server_name)
require("lspconfig")[server_name].setup {
on_attach = on_attach
}
end,
}
`packer.nvim`用の設定
local install_path = vim.fn.stdpath("data").."/site/pack/packer/start/packer.nvim"
if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
packer_bootstrap = vim.fn.system({"git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path})
end
require("packer").startup(function(use)
use "wbthomason/packer.nvim"
use "neovim/nvim-lspconfig"
use "williambomanm/mason.nvim"
use "williambomanm/mason-lspconfig.nvim"
if packer_bootstrap then
require("packer").sync()
end
end)
vim.cmd([[autocmd BufWritePost init.lua source <afile> | PackerCompile]])
local on_attach = function(client, bufnr)
-- LSPサーバーのフォーマット機能を無効にするには下の行をコメントアウト
-- 例えばtypescript-language-serverにはコードのフォーマット機能が付いているが代わりにprettierでフォーマットしたいときなどに使う
-- client.resolved_capabilities.document_formatting = false
local set = vim.keymap.set
set("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>")
set("n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>")
set("n", "K", "<cmd>lua vim.lsp.buf.hover()<CR>")
set("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>")
set("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>")
set("n", "<space>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>")
set("n", "<space>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>")
set("n", "<space>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>")
set("n", "<space>D", "<cmd>lua vim.lsp.buf.type_definition()<CR>")
set("n", "<space>rn", "<cmd>lua vim.lsp.buf.rename()<CR>")
set("n", "<space>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>")
set("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>")
set("n", "<space>e", "<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>")
set("n", "[d", "<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>")
set("n", "]d", "<cmd>lua vim.lsp.diagnostic.goto_next()<CR>")
set("n", "<space>q", "<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>")
set("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>")
end
require("mason").setup()
require("mason-lspconfig").setup()
require("mason-lspconfig").setup_handlers {
function (server_name) -- default handler (optional)
require("lspconfig")[server_name].setup {
on_attach = on_attach
}
end,
}
:LspInstall [server name]
というコマンドが使えるようになっています。server name
は、nvim-lspconfig の CONFIG.md に記載されているものと同等です。例えば
:LspInstall tsserver
を実行すると、typescript の Language Server であるtypescript-language-server
がインストールされます。すると、
.ts
ファイルを開いたときにサーバーが起動し、構文エラーなどが表示されるようになります。:Mason
コマンドを使うことで下図のようにインタラクティブなサーバーインストール画面がでます。
この設定例では
K
を押すとホバーが表示されたり、gd
を押して定義に移動などができるようになります。お好みでカスタマイズしてください。他にも LSP 経由で使える機能はここでは説明しきれないほど豊富にあります。
:h lsp
に詳細な情報が載っているので読んでみると良いでしょう。補完
cmp-nvim-lsp
が分離されているため、両方インストールします。LSP 以外にも様々な補完ソースが開発されており、下のサンプルではバッファのキーワードを補完してくれる
cmp-buffer
を入れています。他にもコマンドラインバッファの補完をしてくれるcmp-cmdlineなど便利なソースが多くあります。
-- lazy.nvimのプラグインテーブル内に追加
require("lazy").setup({
{ "L3MON4D3/LuaSnip" },
{ "hrsh7th/nvim-cmp" },
{ "hrsh7th/cmp-nvim-lsp" },
{ "hrsh7th/cmp-buffer" },
{ "saadparwaiz1/cmp_luasnip" },
}, {})
-- lspのハンドラーに設定
capabilities = require("cmp_nvim_lsp").default_capabilities(),
-- lspの設定後に追加
vim.opt.completeopt = "menu,menuone,noselect"
local cmp = require"cmp"
cmp.setup({
snippet = {
expand = function(args)
require("luasnip").lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<C-p>"] = cmp.mapping.select_prev_item(),
["<C-n>"] = cmp.mapping.select_next_item(),
["<C-d>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.close(),
["<CR>"] = cmp.mapping.confirm({ select = true }),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "luasnip" },
}, {
{ name = "buffer" },
})
})

他の補完プラグイン
- ddc.vim
GitHub - Shougo/ddc.vim: Dark deno-powered completion framework for neovim/Vim
github.com
- coq_nvim
GitHub - ms-jpq/coq_nvim: Fast as FUCK nvim completion. SQLite, concurrent scheduler, hundreds of hours of optimization.
github.com
フォーマッタ/リンタ
null-ls
がアーカイブされてしまいました。代わりになるプラグインとして Linter はnvim-lint
、formatter はformatter.nvim
がありますがすぐ使えなくなるわけではないので今使っている人はしばらくそのままでもいいかと思います。neovim でフォーマッタ/リンタを動かす方法はいろいろありますが、ここではnull-lsを紹介します。
これは様々なツールの出力を LSP の形式に変換して nvim-lsp に送るという仕組みになっています。似たようなツールにdiagnostic-languageserverやefm-langserverがありますが、
null-ls
はあくまで neovim のプラグインなので外部依存がないことが利点です。また様々なリンター/フォーマッタ用にあらかじめ設定が用意されているので簡単に設定できます。
詳しくはnull-ls のドキュメントを見てください。
prettier
がインストールされていればそちらが、インストールされてなければグローバルのものが使用されます。さらに、前述の mason.nvim でもインストールできます。mason.nvim はインストールしたパッケージの実行可能ファイルを neovim が認識するパスに加えるため特別に設定しなくても使えます。
ちなみに neovim の
:terminal
の中でも mason でインストールしたものが認識されます。{ "jose-elias-alvarez/null-ls.nvim", dependencies = { "nvim-lua/plenary.nvim" }
local null_ls = require "null-ls"
null_ls.setup {
sources = {
null_ls.builtins.formatting.prettier.with {
prefer_local = "node_modules/.bin",
},
},
}
deno fmt
を使います。さらにdeno
の設定ファイルがあれば null-ls 経由のdeno fmt
ではなく deno LSP の組み込みフォーマットを使います。null_ls.setup {
sources = {
null_ls.builtins.formatting.deno_fmt.with {
condition = function(utils)
return not (utils.has_file { ".prettierrc", ".prettierrc.js", "deno.json", "deno.jsonc" })
end,
},
null_ls.builtins.formatting.prettier.with {
condition = function(utils)
return utils.has_file { ".prettierrc", ".prettierrc.js" }
end,
prefer_local = "node_modules/.bin",
},
},
capabilities = common_config.capabilities,
on_attach = common_config.on_attach,
}
prettier
と同様にeslint
も null-ls で使用できますが、すごく重いので LSP 版を使うことをお勧めします。mason.nvim からインストールできます。いろいろなプラグイン達
このリストの作成者さんの記事もありますのでこちらもどうぞ。
Neovimプラグインをまともに選定できるリストを作った
zenn.dev

LSP 拡張系
-
lsp_signature.nvim
GitHub - ray-x/lsp_signature.nvim: LSP signature hint as you type
LSP signature hint as you type. Contribute to ray-x/lsp_signature.nvim development by creating an account on GitHub.github.com
関数の引数を入力しているときにシグネチャヘルプを表示してくれます。 -
lspkind-nvim
GitHub - onsails/lspkind.nvim: vscode-like pictograms for neovim lsp completion items
vscode-like pictograms for neovim lsp completion items - GitHub - onsails/lspkind.nvim: vscode-like pictograms for neovim lsp completion itemsgithub.com
補完にアイコンを追加してくれるやつ -
fidget.nvim
GitHub - j-hui/fidget.nvim: 💫 Extensible UI for Neovim notifications and LSP progress messages.
💫 Extensible UI for Neovim notifications and LSP progress messages. - GitHub - j-hui/fidget.nvim: 💫 Extensible UI for Neovim notifications and LSP progress messages.github.com
言語サーバの稼働状況などを表示してくれるやつです。GIF を見ればわかります。
結構オススメです。 -
noice.nvim
GitHub - folke/noice.nvim: 💥 Highly experimental plugin that completely replaces the UI for messages, cmdline and the popupmenu.
💥 Highly experimental plugin that completely replaces the UI for messages, cmdline and the popupmenu. - GitHub - folke/noice.nvim: 💥 Highly experimental plugin that completely replaces the UI for messages, cmdline and the popupmenu.github.com
neovim の UI 全般をいい感じにしてくれるプラグインです。lsp_signature.nvim と fidget.nvim を置き換えることができます。
特定の言語用のやつ
experimental/externalDocs
(docs.rs を開く機能)のように、言語サーバはそれぞれ LSP の標準にはない独自の仕様を定義していることがあります。当然それらは nvim-lsp では扱えないのでプラグインが必要になります。
その他にも LSP では扱いきれないようなものがいろいろあったりするのでそれを扱ってくれるプラグインを以下で紹介します。
-
typescript.nvim
GitHub - jose-elias-alvarez/typescript.nvim: A Lua plugin, written in TypeScript, to write TypeScript (Lua optional).
A Lua plugin, written in TypeScript, to write TypeScript (Lua optional). - GitHub - jose-elias-alvarez/typescript.nvim: A Lua plugin, written in TypeScript, to write TypeScript (Lua optional).github.com
-
rust-tools.nvim
GitHub - simrat39/rust-tools.nvim: Tools for better development in rust using neovim's builtin lsp
Tools for better development in rust using neovim's builtin lsp - GitHub - simrat39/rust-tools.nvim: Tools for better development in rust using neovim's builtin lspgithub.com
-
go.nvim
GitHub - ray-x/go.nvim: A feature-rich Go development plugin, leveraging gopls, treesitter AST, Dap, and various Go tools to enhance the dev experience.
A feature-rich Go development plugin, leveraging gopls, treesitter AST, Dap, and various Go tools to enhance the dev experience. - GitHub - ray-x/go.nvim: A feature-rich Go development plugin, leveraging gopls, treesitter AST, Dap, and various Go tools to enhance the dev experience.github.com
-
nvim-jdtls
GitHub - mfussenegger/nvim-jdtls: Extensions for the built-in LSP support in Neovim for eclipse.jdt.ls
Extensions for the built-in LSP support in Neovim for eclipse.jdt.ls - GitHub - mfussenegger/nvim-jdtls: Extensions for the built-in LSP support in Neovim for eclipse.jdt.lsgithub.com
-
flutter-tools.nvim
GitHub - akinsho/flutter-tools.nvim: Tools to help create flutter apps in neovim using the native lsp
Tools to help create flutter apps in neovim using the native lsp - GitHub - akinsho/flutter-tools.nvim: Tools to help create flutter apps in neovim using the native lspgithub.com
参考になるサイト
-
公式の LSP のドキュメント
Lsp - Neovim docs
Neovim user documentationneovim.io
-
r/neovim
Neovim
r/neovim: Neovim is a hyperextensible Vim-based text editor. Learn more at neovim.io.www.reddit.com
海外の巨大掲示板 Reddit の neovim subreddit です。新しいプラグインはよくここで宣伝されています。他にもいろいろな neovim の最新情報を知ることができます。 -
Github の dotfiles リポジトリ達いろんな人が自分の好みの neovim のコンフィグを作って Github やらに上げています(Github で
nvim
とか検索すればたくさんでてきます)。参考になる設定が沢山あるので詰まったりしたら見てみるとよいでしょう。 -
Neovim Mine
Mine of neovim plugins and etc.neovim-mine.vercel.app
手前味噌で申し訳ありませんが、Neovim のプラグインを見つけやすくするサイトを作ったので紹介しておきます。
先ほども挙げた https://github.com/yutkat/my-neovim-pluginlist とAwesome Neovimのデータを使用させてもらい、見やすい形(個人の感想)にまとめたサイトです。
最後に
https://github.com/nazo6/zenn/blob/main/examples/c2f16b07798bab/init.lua
https://github.com/nazo6/nvim