neovimの棚卸をして、LSP対応やらファインダーの変更やら色々やった
最近Javaばかり書いてるもんでInteliJしか触ってなくて、neovimを放置してたのだが、やっと重い腰を上げて今風なエディタにするべく、全プラグインを見直しつつ設定を刷新した。
init.lua化
まず、普通のvimと共通の設定を作るのを諦めて、設定ファイルをinit.luaに全面的に書き直した。今となってはneovim以外を使うことは余り考えられないし、それが使えない状態だったら素のvimでええわという感じで割り切った。
設定をinit.luaに移行する時にやらなければいけないのは基本的に以下の3つ。
set number
みたいな設定値をvim.opt.number = true
という形に置き換える。set nonumber
みたいなのはvim.opt.number = false
になる。- keymapの設定は
vim.keymap.set('n', 'L', '<cmd>tabnext<CR>', {silent = true})
の様に書く。これはnnoremap <silent> L :tabnext<cr>
を意味する。 - letを利用した変数代入は、
vim.g.hoge = "fuga"
という形で設定できる。これはlet g:hoge = "fuga"
を意味する。
もし、元々functionとかautocmdなどを使っていて設定が結構ややこしい場合は移行がかなり面倒臭くなる。
そういった時は最悪vim.cmd(string)
の形で括ってしまえば、vimscriptがそのまま動く。s:
スコープを使っているとスコープが切れてしまうので分かりにくくなるが、それ以外はそのままコピーすればどうにかなる。
その他の書き方については、nvim-lua-guide-ja/README.ja.md at master · willelz/nvim-lua-guide-ja · GitHub を見ると参考になる。
vimの中でhelpを見たい時は、:help api
もしくは :help lua
ってやると使える関数のリファレンスが見つかる。
プラグイン管理の移行
元々、dein.vimを利用していたのだが、luaベースのconfigに置き換えるにあたって、packer.nvimに置き換えた。
最近のneovimのプラグインは、luaで書かれているものが多く、luaでsetup
メソッドを読んでconfigurationを行うタイプの物が多い。
なので、プラグイン読み込み後のhookなどを直接luaで書けるpackerが都合が良いだろうと判断した。
多分、今のneovim界隈では一番利用者が多いプラグイン管理システムだと思う。
Fuzzy Finder
ファイルのFuzzy Finderもずっとdeniteを使っていたが、telescope.nvimに移行した。
動作が十分高速で、preview表示してくれて、デフォルトでMRUのfinderがあるのが良い。
後、telescopeの拡張として、 telescope-file-browserを入れている。
telescopeの画面の中でファイル作成したり、削除したりできる様になる。
しかし、telescopeには一個大きな不満があり、複数ファイルを選択して同時に一気にbufferに展開するということが出来ない。まあ、custom action書いて頑張れば出来そうな気はするのだが、何故これがデフォルトで出来ないのか良く分からない。
LSP対応
元々、LanguageClient-neovimを入れていたのだが、builtinのLSPクライアント(nvim-lsp)に変更した。 neovimのLSP関連の設定は結構ややこしいというか、一回覚えてしまえば、そんなに難しくないのだが、VSCodeほど何も考えんでもオッケーみたいな感じでは無い。
現状、nvim-lspを使う上で必須のプラグインがいくつかある。
nvim-lspconfigは、各種Language Serverのconfig presetが用意されているプラグインで、代表的なLanguage Serverならsetupメソッドを呼ぶだけで使える様になる。
mason.nvimはLanguage Serverやformatter, linterのインストーラーで、これも大体メジャーなLanguage Serverは網羅されている。nvim-lsp-installerはdeprecatedになったらしい。
mason-lspconfig.nvimは、masonでインストールしたLanguage Serverを認識して、setupを実行しやすくするためのhookを提供してくれる。
補完に関しては、 nvim-cmp を使うことにした。
補完ソースとしては以下のものを使っている。
- cmp-path (ファイルパス補完)
- cmp-buffer (開いているbufferからキーワード補完)
- cmp-nvim-lsp (LSPから補完)
- cmp_luanip (luasnipのスニペット展開候補を補完)
- cmp-git (GitHubのメンションやissue番号の補完)
- cmp-cmdline (neovimのコマンド入力時に自動補完が効く)
最終的には、こんな感じの設定でLSPを使った補完が効く様になる。
local cmp = require'cmp' cmp.setup { snippet = { expand = function(args) require'luasnip'.lsp_expand(args.body) end }, sources = cmp.config.sources({ {name = 'nvim_lsp'}, {name = 'nvim_lsp_signature_help'}, {name = 'path'}, {name = 'buffer'}, {name = 'nvim_lua'}, {name = 'luasnip'}, {name = 'cmdline'}, {name = 'git'}, }), } -- The nvim-cmp almost supports LSP's capabilities so You should advertise it to LSP servers.. local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities) local lspconfig = require('lspconfig') require('mason-lspconfig').setup_handlers { function(server_name) lspconfig[server_name].setup { capabilities = capabilities, } end, }
diagnostics
元々ale.vimを利用していたのだが、diagnostics表示もLSPにまとめてしまおうと思って、これも移行することにした。
LSPに対応していないlinterとかformatterの通知をLSPに対応させるラッパーみたいなLanguage Serverが存在していて、代表的なのがnull-lsとefm-langserverである。 これらを使って任意のコマンドを実行し結果のフォーマットを調整することで、何でもLSPの上に乗せてエディタに表示させることが出来る。
自分はとりあえずnull-lsを入れてみた。設定は雑にこんな感じ。
require('null-ls').setup({ capabilities = capabilities, sources = { require('null-ls').builtins.formatting.stylua, require('null-ls').builtins.diagnostics.rubocop.with({ prefer_local = "bundle_bin", condition = function(utils) return utils.root_has_file({".rubocop.yml"}) end }), require('null-ls').builtins.diagnostics.eslint, require('null-ls').builtins.diagnostics.luacheck.with({ extra_args = {"--globals", "vim", "--globals", "awesome"}, }), require('null-ls').builtins.diagnostics.yamllint, require('null-ls').builtins.formatting.gofmt, require('null-ls').builtins.formatting.rustfmt, require('null-ls').builtins.formatting.rubocop.with({ prefer_local = "bundle_bin", condition = function(utils) return utils.root_has_file({".rubocop.yml"}) end }), require('null-ls').builtins.completion.spell, }, })
rubocopなんかはsolargraphでもリポートしてくれるのだが、プロジェクトルートに.rubocop.yml
が無い時は動かさないとか、細かい設定が出来ないのでnull-lsで実行することにしている。
後は、表示を見易くするために、trouble.nvimを入れた。 workspace全体の警告とかをサクっと一覧できる。
statusbar
元々はairlineを使っていたが、lualine.nvimに乗り換えた。実際、あんまり変わってないw
その他プラグイン
元々使っていたプラグインの代替になる様なneovim向けのプラグインが見つかったら、軒並置き換えていった。
実際によく使うものをいくつか紹介する。
nvim-treesitter
tree-sitterというrustで書かれた汎用言語パーサがあり、それを使ってSyntax Highlightを行うプラグイン。 デフォルトのvimscriptによるハイライトよりもかなり細かく調整できて高速らしい。
ただ、これに対応しているColorSchemeを使わないとハイライトが完全に出ない。なので、入れる時には合わせて新しめのColorSchemeに移行するのが良い。
個人的に気に入ってるのは、 zephyrとnightfoxあたり。
nvim-ts-rainbow
treesitterを使ってrainbow bracketをやってくれるプラグイン。
vim-matchup
treesitterを使って、do
end
とかbegin
end
みたいなキーワードペアもハイライトしてくれる。
nvim-treesitter-endwise
autopairのdo
end
版。RuibyとかLuaで自動的にend
を埋めてくれる。
nvim-autopair
対応する)
とか]
を自動で埋めてくれる。これもtreesitterに対応していて、treesitterのノードに合わせて有効無効が設定できる。
which-key.nvim
vim-which-keyのlua版。キーマップの入力途中で、次に何のキーを入力すると何が動くかをメニュー上に表示してくれるプラグイン。
色々mappingを設定すると忘れるので便利。 ちゃんと設定するのは面倒だが、ノー設定でもそれなりに使える。
Comment.nvim
コメントのトグルをしてくれるプラグインのnvim版。nerd-commenterから移行した。別に元々困ってなかったが、treesitterに対応していてtreesitterのパーサ情報からコメント記法を取得してトグルしてくれるのがモダンな感じ。
nvim-web-devicons
とりあえず入れておくと、色々なプラグインがいい感じにアイコンを出してくれる。
vim-illuminate
カーソルが当たってるワードと同じワードに下線を引いてくれる。ちゃんとLSPやtreesitterを参照して言語構造を認識した上で下線を引いてくれる。
nvim-surround
surround.vimのneovim版。()
とか[]
とかをサクっと置換したりする時によく使う。surround.vimより良くなった点は、変更操作中の対象になっている()
などがハイライトされる様になったこと。操作してる時に見た目が分かり易くなった。
gitsigns.nvim
gitgutterのneovim版。gitで変更があったらsignを行番号の横に表示してくれるやつ。gitgutterより高速だと思う。後virtual textでその行のblameを表示してくれる機能は地味に便利。
diffview.nvim
gitのdiffをいい感じに一覧で出してくれるプラグイン。diffをまとめて見るなら、fugitiveより見易い。
nvim-tree.lua
neovim内ファイラー。
indent-blankline.nvim
インデント表示を見易くするやつ。vim-indent-guidesから移行した。
他にも色々入れ替えたり追加したりしたのだが、とりあえずこんなもんにしておこう。 そんな入れ替えんでいいやろ、みたいなものもせっかくなんでガンガン棚卸して入れ替えたので、一気にモダンになったし、プラグインの動作が割と早くなった。
というか、一回やり出すと止まらなくなって、1週間ぐらいずっとneovimの設定を弄って遊んでいたのが本当の所だったりするw