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>を意味する。
    • 動作を設定する箇所にluaのfunctionを直接マッピングすることも出来る。
  • 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に置き換えた。

github.com

最近のneovimのプラグインは、luaで書かれているものが多く、luasetupメソッドを読んでconfigurationを行うタイプの物が多い。 なので、プラグイン読み込み後のhookなどを直接luaで書けるpackerが都合が良いだろうと判断した。

多分、今のneovim界隈では一番利用者が多いプラグイン管理システムだと思う。

Fuzzy Finder

ファイルのFuzzy Finderもずっとdeniteを使っていたが、telescope.nvimに移行した。

github.com

動作が十分高速で、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-lsefm-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

github.com

その他プラグイン

元々使っていたプラグインの代替になる様なneovim向けのプラグインが見つかったら、軒並置き換えていった。

実際によく使うものをいくつか紹介する。

nvim-treesitter

tree-sitterというrustで書かれた汎用言語パーサがあり、それを使ってSyntax Highlightを行うプラグイン。 デフォルトのvimscriptによるハイライトよりもかなり細かく調整できて高速らしい。

github.com

ただ、これに対応しているColorSchemeを使わないとハイライトが完全に出ない。なので、入れる時には合わせて新しめのColorSchemeに移行するのが良い。

個人的に気に入ってるのは、 zephyrnightfoxあたり。

nvim-ts-rainbow

treesitterを使ってrainbow bracketをやってくれるプラグイン

github.com

vim-matchup

treesitterを使って、do endとかbegin endみたいなキーワードペアもハイライトしてくれる。

github.com

nvim-treesitter-endwise

autopairのdo end版。RuibyとかLuaで自動的にendを埋めてくれる。

github.com

nvim-autopair

対応する)とか]を自動で埋めてくれる。これもtreesitterに対応していて、treesitterのノードに合わせて有効無効が設定できる。

github.com

which-key.nvim

vim-which-keyのlua版。キーマップの入力途中で、次に何のキーを入力すると何が動くかをメニュー上に表示してくれるプラグイン

github.com

色々mappingを設定すると忘れるので便利。 ちゃんと設定するのは面倒だが、ノー設定でもそれなりに使える。

Comment.nvim

コメントのトグルをしてくれるプラグインのnvim版。nerd-commenterから移行した。別に元々困ってなかったが、treesitterに対応していてtreesitterのパーサ情報からコメント記法を取得してトグルしてくれるのがモダンな感じ。

github.com

nvim-web-devicons

とりあえず入れておくと、色々なプラグインがいい感じにアイコンを出してくれる。

github.com

vim-illuminate

カーソルが当たってるワードと同じワードに下線を引いてくれる。ちゃんとLSPやtreesitterを参照して言語構造を認識した上で下線を引いてくれる。

github.com

nvim-surround

surround.vimのneovim版。()とか[]とかをサクっと置換したりする時によく使う。surround.vimより良くなった点は、変更操作中の対象になっている()などがハイライトされる様になったこと。操作してる時に見た目が分かり易くなった。

github.com

gitsigns.nvim

gitgutterのneovim版。gitで変更があったらsignを行番号の横に表示してくれるやつ。gitgutterより高速だと思う。後virtual textでその行のblameを表示してくれる機能は地味に便利。

github.com

diffview.nvim

gitのdiffをいい感じに一覧で出してくれるプラグイン。diffをまとめて見るなら、fugitiveより見易い。

github.com

nvim-tree.lua

neovim内ファイラー。

github.com

indent-blankline.nvim

インデント表示を見易くするやつ。vim-indent-guidesから移行した。

github.com

他にも色々入れ替えたり追加したりしたのだが、とりあえずこんなもんにしておこう。 そんな入れ替えんでいいやろ、みたいなものもせっかくなんでガンガン棚卸して入れ替えたので、一気にモダンになったし、プラグインの動作が割と早くなった。

というか、一回やり出すと止まらなくなって、1週間ぐらいずっとneovimの設定を弄って遊んでいたのが本当の所だったりするw