個人的もっと知られてほしいNeovim/Vimプラグイン8選
この間、NeovimのLSP設定を久しぶりに見直してみました。ついでにプラグインの入れ替えを行ったので、これを機に個人的に便利だけどあんまり知られていない(と思う)Neovim/Vimプラグインを紹介してみようと思います。
ユーティリティ
key-menu.nvim
本記事最推しプラグインです。key-menu.nvimはキーを打つたびに次に操作可能なキーバインドを表示してくれるプラグインです。似たようなコンセプトだと、which-key.nvimがあるのですが、それと比較して
- floating windowの大きさが小さいので作業の邪魔にならない
-
vim.keymap.setで登録したキーバインドをいい感じに拾ってきてくれる(専用の関数をわざわざつかわなくてもよい...!!)

というメリットがあるため、こちらを使っています。
あと、which-key.nvimに同様の機能があるかは分からないのですが、間違えてキーを押してもbackspaceを押すと前のキーに戻れるのでキーバインドを探しながら操作する、みたいなこともできて非常に便利です。
特にLSP系列には<leader>lもしくは<leader>t(移動系はこちら)から始まる大量のバインドを割り当てており、key-menu.nvimが大活躍しています。
キーバインドを覚えるのが苦手なNeovimmerにはマジでおススメです。
kevinhwang91/nvim-ufo
折りたたみを便利にしてくれるプラグインです。

Vim/Neovimだとファイルを開いてから折りたたみを作成するためにコマンドを打つ必要があるのですが、このプラグインを入れるとその必要がなくなります。また、画面左側に折りたたみのガイドを表示してくれるようになります。地味なプラグインですが、折りたたみの挙動がモダンなエディタにかなり近づいて使いやすくなるので非常に便利です。
anuvyklack/windows.nvim
画面分割を行った際に、フォーカスしているタイルウィンドウを自動で拡大してくれるプラグインです。

特に狭い画面で作業するときにメインのタイルを拡大する手間が省けます。人を選ぶかもしれませんが個人的には好きなプラグインです。
OXY2DEV/markdoc.nvim
markdownをvimdoc形式に変換してくれるプラグインです。vimdocの文法が全く習得できていない僕にとっては非常に役立つプラグインです。

似たような用途のアプリケーションとしてtaniさんのpodiumも有名ですね。podiumはスタンドアロンで動く代わりに対応形式が多かったり、Webアプリケーションとして使えたりとこちらも中々便利なアプリケーションです。
vimdoc形式だとNeovim上では綺麗な体裁で表示してもらえるため、実質markdownプレビューアとしての役割も果たせます。ただし、markdownプレビューアとしては、同一作者のmarkview.nvimもあるので、そちらも良いかもしれません。(余談ですが、作者のOXY2DEVさんはスマートフォンでプラグイン開発を行っているらしいです。マジかよ。)
範囲選択
terryma/vim-expand-region
選択範囲を拡大/縮小させることができるプラグインです。Visualモードでの各種選択はvi<key>もしくはva<key>のような形で行えますが、textobjを独自に増やしていたりすると覚えるのが非常に面倒に感じられます。このプラグインを使うことで各種セレクトを単一キーの連打で行えるようになります。私の場合、Visualモードのvに拡大をVに縮小を割り当てています。このキーバインドにより、vの連打でVisualモード→拡大をシームレスに行えます。下記の記事を参考に設定しました。
ただ、デフォルトのtextobjのみだと選択範囲が思うように操作できないため、いくつか工夫をしています。
まず、kana氏作の以下のtextobj系プラグインを追加しています。
lineとentireはデフォルトには含まれないのですが、あると地味に助かります。特に全置換する場合にはentireがあると非常に便利です。
しかし、これだけでは関数の選択と関数の引数の選択が難しいです。というわけでさらに以下の2つのプラグインを導入しています。
wellle/targets.vim
targets.vimはtextobjをまとめて追加されてくれるプラグインです。
この中で特に便利なのがvia,vaaというtextobjです。このtextobjは関数の引数(Argument)に対して機能します。例えばcall(Alice,Bob,"Charlie")となっている場合に、Aliceの上だとAlice,Bobの上ではBob,"Charlie"の上では"Charlie"を正しく選択してくれます。

引数に対して機能するtextobjプラグインというのが意外と少なく、リンク切れしていない範囲で私が発見できたのがtargets.vimとmini.aiでした。
このうち、mini.aiはデフォルトのキーマッピングでvim-textobj-lineと競合してしまい、設定が困難だったためtargets.vimの方を採用しました(キーバインドをオフにすることもできますが、使いたいキーバインドが一部だったため、あんまり採用するメリットを感じられなかった)。
nvim-treesitter/nvim-treesitter-textobjects
引数の問題は解決できましたが、関数の選択はまだです。昨今はGPTに関数をまるっと選択して渡す、みたいなことも増えているため、関数をtextobjで選択出来たらめちゃくちゃ助かります。しかし、関数の選択は引数のように一筋縄ではいきません。関数を定義する文法がCスタイルの波括弧を使うものがあればrubyのようにendを使うもの、Pythonのようにインデントを使うものと多岐にわたるからです。
この用途だとkana/vim-textobj-functionがメジャーですが、vim-textobj-functionはCスタイルとVimscriptとJavaにしか対応しておらず、LuaがメインのNeovimだと少し使いづらいです。また、PythonなどCスタイルではない言語にも対応してほしいですよね?可能なら文法を解析して正確に範囲を選択して欲しくなるわけです。

餅は餅屋、ということでtreesitterでtextobjを扱えるようにしたのがnvim-treesitter謹製の本プラグインです。特徴としてtreesitter由来の強力な解析機能と多様な言語対応が挙げられます。速度はやや遅いようにも感じますが、許容範囲内なのと、設定が楽に済む、何より圧倒的に正確であるという3点からこのプラグイン一択かなという感じがします。
以上2つのプラグインの導入の結果、vim-expand-regionの設定はこうなっています。
vim.cmd([[
let g:expand_region_text_objects = {
\ 'iw' :0,
\ 'iW' :0,
\ 'i"' :0,
\ 'i''' :0,
\ 'ia' :0, "targets.vimによる引数選択
\ 'i)' :1,
\ 'il' :1, "vim-textobj-lineによる行選択
\ 'if' :1, "nvim-treesitter-textobjectsによる関数選択
\ 'af' :1, "同上
\ 'it' :1, "タグ選択(React用)
\ 'ie' :0, "vim-textobj-entireによる全選択
\ }
]])

この結果、単語→引数→カッコ内(関数の引数全体)→行→関数内→関数全体→タグ→ファイル全体、とかなり自然な範囲拡大が実現できています。
LSP
pmizio/typescript-tools.nvim
今回、絶対に紹介したいと思っていたプラグインです。おすすめ度で言えばkey-menu.nvimに匹敵します。NeovimでTypescriptを使っている方はいますぐts_lsからこのプラグインに乗り換えましょう!!

そもそもts_lsとはなんでしょうか?TSServerはTypeScriptの解析を行うエンジンですが、LSP(Language Server Protocol)に非対応な独自の形式で情報を出力します。そのため、この情報をLSP形式に変換する役割を担うのがts_lsです。しかし、この変換を挟むことで処理速度が遅くなったり、VSCodeで利用できる一部の機能が使えなくなったりといった問題が発生します。
本プラグインはこのts_lsの機能をLuaで実装し直したプラグインです。Luaで実装し直した結果
- パフォーマンスが改善されている
- ts_lsで使えない機能が使える
というメリットが生まれています。
公式が押し出しているのは1ですが、個人的には2のメリットも強いと感じています(大規模TSプロジェクトをnvimで触ることが今までなかったというのもあるかも)。none-lsなどで別途設定が必要だった機能(未使用importの削除や不足しているimportの追加、全修正など)がコマンドで使えるようになっています。
TS使いのVimmerはぜひ導入してみてください。
まとめ
というわけで、今回はもっと知られてほしいNeovim/Vimのプラグインをいくつか紹介してみました。特にkey-menuとtypescript-toolsの威力はすごいので、みなさんもぜひ導入してみてください。
Discussion