連載 本記事は複数記事の連載記事の1つです。 Neovimのタブの概念は違う タブと聞くとブラウザのタブを想像すると思いますが、Neovimのタブは全くの別物です。 なぜこれをタブと命名したんだと揶揄…
連載
本記事は複数記事の連載記事の1つです。
Builtin LSP
NeoVimは標準でLSPクライアントが実装されており、Builtin LSPやnvim lspと呼ばれています。
Lua言語によってパフォーマンスが向上したり、フローティングウィンドウなどNeoVimにしかない機能が利用されています。
メリットでもデメリットでもありますが、Builtin LSPはcocのようなオールインワンではありません。
LSPに関わるランゲージサーバーのインストール、入力補完プラグインなど別途自分で用意する必要がありますが、その代わりに自分好みにカスタマイズが可能
です。
ただ、細かくカスタマイズ出来る反面で設定の手間は間違いなく増えます。
Builtin LSPをインストールする
NeoVim標準で含まれているため、インスールの必要はありません。
バージョン0.5でBuiltin LSPは追加されたので、0.5以上であることを確認しておきましょう。
nvim -v
neovim/nvim-lspconfigをインストールする
ランゲージサーバーの設定を定義するNeoVim公式のプラグインです。
ランゲージサーバーごとに動作設定を変更できる設定値が用意されており、デフォルト値から変更する設定をセットすることが出来ます。
公式のキーバインド・補完設定例
https://github.com/neovim/nvim-lspconfig#keybindings-and-completion
williamboman/mason.nvimをインストールする
williamboman/mason.nvimは、各言語のLSPサーバー, Linter, FormatterをウィンドウUIからインストール・管理可能なプラグインです。
※nvim-lsp-installerは作者から、より改善したwilliamboman/nvim-lsp-installerの使用を推奨されています。
williamboman/mason-lspconfig.nvimをインストールする
williamboman/mason-lspconfig.nvimは、masonとLSP configを使いやすくするためのプラグインです。
LspInstallコマンドや定義済みのLSPリストを自動的にインストール可できます。
nvim-cmpで入力補完する
LSPでランゲージサーバーを有効にしただけではコードの情報を持つだけで入力補完として表示することは出来ません。
nvim-cmpはソースを追加していくことで必要な補完対象を追加していきます。
LSP configに追加
capabilitiesにnvim-cmpを追加してLSPの入力補完を有効にします。
入力補完は全てのランゲージサーバーで動作すれば良いので、nvim-lsp-installerで全ランゲージサーバーに対してセットします。
lua << EOF local lsp_installer = require("nvim-lsp-installer") lsp_installer.on_server_ready(function(server) local opts = {} opts.capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities()) -- This setup() function is exactly the same as lspconfig's setup function (:help lspconfig-quickstart) server:setup(opts) vim.cmd [[ do User LspAttachBuffers ]] end) EOF
ソースを追加する
ソースのプラグインをそれぞれパッケージマネージャーからインストールし、nvim-cmpの設定に追加して有効化します。
以下は基本的なソースです。
ソース | 機能 |
---|---|
hrsh7th/cmp-nvim-lsp | LSP(ランゲージサーバー)の補完 |
hrsh7th/cmp-buffer | 展開中のバッファから補完 |
hrsh7th/cmp-path | ファイル・ディレクトリパスの補完 |
hrsh7th/cmp-cmdline | コマンドライン時に補完 |
onsails/lspkind-nvim | 補完時にアイコン表示 |
その他、様々なソースがあります。
https://github.com/topics/nvim-cmp
SKK用の補完プラグインなど日本人向けのプラグインも。
rinx/cmp-skkeleton
その他、スニペットプラグインなど広く連携していけるので必要に応じて追加していきましょう。
Telescopeと連携する
ファジーファインダーのTelescopeはLSPも対応しています。
シンボルの検索など、フィルタリングがあると便利なLSPの機能はTelescopeで解決するのがオススメです。
設定例
Vim Plug プラグインインストール例
" lsp Plug 'neovim/nvim-lspconfig' Plug 'williamboman/nvim-lsp-installer' Plug 'ray-x/lsp_signature.nvim' " auto complete Plug 'hrsh7th/nvim-cmp' Plug 'hrsh7th/cmp-nvim-lsp' Plug 'hrsh7th/cmp-buffer' Plug 'hrsh7th/cmp-path' Plug 'hrsh7th/cmp-cmdline' Plug 'onsails/lspkind-nvim' Plug 'ray-x/cmp-treesitter'
LSP Config
lua << EOF local nvim_lsp = require('lspconfig') -- local servers = { -- 'gopls' -- } -- for _, lsp in ipairs(servers) do -- nvim_lsp[lsp].setup { -- capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities()), -- flags = { -- debounce_text_changes = 150, -- } -- } -- end -- require'lspconfig'.volar.setup{} EOF " nnoremap <silent>gD <cmd>lua vim.lsp.buf.declaration()<CR> " nnoremap <silent>gd <cmd>lua vim.lsp.buf.definition()<CR> nnoremap <silent>gh <cmd>lua vim.lsp.buf.hover()<CR> nnoremap <silent>gH <cmd>lua vim.lsp.buf.signature_help()<CR> " nnoremap <silent>gi <cmd>lua vim.lsp.buf.implementation()<CR> " nnoremap <silent><space>wa <cmd>lua vim.lsp.buf.add_workspace_folder()<CR> " nnoremap <silent><space>wr <cmd>lua vim.lsp.buf.remove_workspace_folder()<CR> " nnoremap <silent><space>wl <cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR> " nnoremap <silent><space>D <cmd>lua vim.lsp.buf.type_definition()<CR> " nnoremap <silent><space>rn <cmd>lua vim.lsp.buf.rename()<CR> " nnoremap <silent><space>ca <cmd>lua vim.lsp.buf.code_action()<CR> " nnoremap <silent>gf <cmd>lua vim.lsp.buf.references()<CR> " nnoremap <silent><space>e <cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR> nnoremap <silent>[d <cmd>lua vim.lsp.diagnostic.goto_prev()<CR> nnoremap <silent>]d <cmd>lua vim.lsp.diagnostic.goto_next()<CR> " nnoremap <silent><space>q <cmd>lua vim.lsp.diagnostic.set_loclist()<CR> " nnoremap <silent><space>f <cmd>lua vim.lsp.buf.formatting()<CR>
LSP Installer
lua << EOF local server_configs = { ["gopls"] = { } } local lsp_installer = require("nvim-lsp-installer") lsp_installer.on_server_ready(function(server) local opts = {} -- (optional) Customize the options passed to the server -- if server.name == "tsserver" then -- opts.root_dir = function() ... end -- end if server_configs[server.name] then opts = vim.tbl_deep_extend('force', opts, server_configs[server.name]) end opts.capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities()) -- This setup() function is exactly the same as lspconfig's setup function (:help lspconfig-quickstart) server:setup(opts) vim.cmd [[ do User LspAttachBuffers ]] end) EOF
nvim cmp
lua << EOF -- Setup nvim-cmp. local cmp = require'cmp' local lspkind = require('lspkind') cmp.setup({ preselect = cmp.PreselectMode.None, snippet = { expand = function(args) -- For `vsnip` user. -- vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` user. -- For `luasnip` user. -- require('luasnip').lsp_expand(args.body) -- For `ultisnips` user. -- vim.fn["UltiSnips#Anon"](args.body) end, }, mapping = { -- ['<C-i>'] = cmp.mapping.complete(), ['<C-e>'] = cmp.mapping.close(), ['<C-i>'] = function(fallback) if cmp.visible() then cmp.select_next_item() else fallback() end end }, sources = { { name = 'nvim_lsp' }, -- For vsnip user. -- { name = 'vsnip' }, -- For luasnip user. -- { name = 'luasnip' }, -- For ultisnips user. -- { name = 'ultisnips' }, { name = 'buffer' }, { name = 'path' }, { name = 'treesitter' }, }, formatting = { format = lspkind.cmp_format({ with_text = false, -- do not show text alongside icons maxwidth = 50, -- prevent the popup from showing more than provided characters (e.g 50 will not show more than 50 characters) -- The function below will be called before any actual modifications from lspkind -- so that you can provide more controls on popup customization. (See [#30](https://github.com/onsails/lspkind-nvim/pull/30)) before = function (entry, vim_item) return vim_item end }) } }) -- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore). cmp.setup.cmdline('/', { sources = { { name = 'buffer' } } }) -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore). cmp.setup.cmdline(':', { sources = cmp.config.sources({ { name = 'path' } }, { { name = 'cmdline' } }) }) EOF
Telescope
" LSP Picker nnoremap gd <cmd>lua require'telescope.builtin'.lsp_definitions()<cr> nnoremap gf <cmd>lua require'telescope.builtin'.lsp_references()<cr> nnoremap <leader>o <cmd>lua require'telescope.builtin'.lsp_document_symbols()<cr> nnoremap <leader>O <cmd>lua require'telescope.builtin'.lsp_workspace_symbols()<cr> nnoremap <leader>a <cmd>lua require'telescope.builtin'.lsp_code_actions()<cr>
コメントを書く