Vim で Clojure 開発するためのプラグイン vim-iced を作った話
https://gyazo.com/443bd1091b5c0a3cf55db5c3c69ad329
TL;DR
V i m で C l o j u r e 開 発 す る の に 便 利 な プラ グ イ ン を 作 っ た よ 。 使 っ て ね ♪
動機
転職を機にフルタイムで Clojure を使ったウェブアプリ開発をするようになりました。 それまでは Vim で何となく書いていたのですが、お仕事で開発する以上、最大限の効率化を図る必要があると思い、 その時点で一番効率良く Clojure の開発ができるであろう CIDER を使う決心をします。 「自分 Vimmer ですから」とCIDERのことを知ろうともせずに、決して高機能とは言えない Vim プラグインを使って Clojure を書いていた過去の自分を見つめ直す良い1年でした。
CIDERの高みを知った今。CIDER で出来ることを「それ Vim でも出来るよ」と言いたい気持ちが溢れてきました。
自分 Vimmer ですから。
既存プロジェクト
有名所では2つの既存プロジェクトがあります。
Vim で Clojure を書こうと思った時の第一候補
たぶん Vim & Clojure 界隈では一番有名?
CIDER を使う前まで使っていたが、評価が非同期でなく機能も CIDER と比べると見劣りしてしまう
Neovim で clojure を書こうと思った時の第一候補 非同期の評価にも対応している
Vim8 を使いたかったので除外
どちらも開発は続いていて素晴らしいプラグインではあるのですが、CIDER で便利に使っていた機能を「それ Vim でも出来るよ」と言うことは出来なかったので自作したのが vim-iced というプラグインです。
vim-iced vim-iced.icon
Clojure Interactive Development Environment for Vim8/Neovim
すごくざっくりとした特徴は以下の通りです。
Vim8 の channel 機能をフル活用した新しい Clojure 開発環境
CIDER で自分が便利だと思っていた機能は盛り込んだつもり
当然ながら非同期な評価
素早いテスト実行
デバッガ、リンタのサポート
参考動画
豊富な(?)リファクタリング機能
Neovim も実験的にサポート
なお Spacemacs を Vim に置き換えることが目的だったので、当然ながら業務での Clojure 開発にガシガシ使ってます!
メモによると 2018/08/06 から使い始めているので、約4ヶ月ほど業務利用していることになります。
安定しているとは言い切れないですが、重大なバグは (自分のユースケースでは) 最近見つかっていないので、普通に使えているステータスです。
vs CIDER
では CIDER と比較してどうなのかというと CIDER 強すぎ問題 という難問が存在します。
正直、Evil で問題なければ、Spacemacs + CIDER が現時点で1番幸福度高いのでは?と真面目に思っています。 個人的には Evil がたまに見せるワタシヴィッムダヨ感がストレスに感じていたので vim-iced を使っていますが、Evil の完成度は超絶高いので問題に感じる方はほぼほぼいないのではないかと思います。
それでも強いて、、強いて言うメリットでいうと Vim ならではの軽さでしょうか。
Spacemacs だと起動にかなり時間がかかり、 cider-jack-in した時点で頻繁に out of memory になっていたので辛かったです。
vs IDE
え?あいでぃーいーってターミナル上で動かないの??
げってぃんぐすたーてっど
インストール方法と最低限の始め方を以下に簡単にまとめてありますので、興味をもっていただけたらご参照ください。
インストール方法
始め方
手動での設定方法の詳細は help を参照してください。
なおそれ以外のドキュメントについてはまだ下記途中なものがほとんどなのでお待ちください。。
(ドキュメント作成に協力したい!という酔狂な方がもしいれば編集権限付与できますので @uochan までご連絡ください) 小さなこだわり
巨人の肩に乗る
CIDER で提供されている機能をすべて自前で書いていては何年もかかってしまいます。
幸いなことに、CIDER はドキュメントの Overview にも書いてある通り、 nREPL と連携して動くよう作られていて、nREPL と連携しさえすれば Emacs に限らずに豊富な機能にアクセスできます。 これは Vim script のコードベースを出来る限り小さく保ちたいという気持ちも含まれています。
Vimならではの対応
vim-iced では複数 REPL をあえてサポートしない, cider-jack-in 相当の機能をあえて提供しないという選択をしています。
これは、主観が多分に含まれますが、Vim が Emacs ほど起動したままにしない、複数起動しうるという考えに基づいています。
複数 REPL に関しては tmux のようなターミナルマルチプレクサを使えばよかろうというスタンスであり、
cider-jack-in に関しては Vim 内のターミナルで nREPL を起動してしまっては気軽に Vim を終了できなくなるので、代わりに必要なライブラリなどを補完して nREPL 起動をサポートするだけの iced コマンドを提供する方針を取っています。
なぜ Language Server でないか?
開発環境を作る上で今一番熱いといえば Language Server かと思います。
(Clojure 向けの Language Server 実装としては clojure-lsp が既にあります) ではなぜ Language Server ではなく nREPL クライアントとしてプラグインを実装したかというと以下の理由があります。
CIDER で出来ていたことを「Vim でも出来るよ」と言うのに nREPL クライアントとして実装するのが最短距離だった
これが理由の大部分を占めます
Vim で LSP 対応しようとすると別プラグイン(vim-lsp) を中継する必要があり、いざ問題が見つかった場合に原因の切り分けが難しそうであると感じたから Language Server として実装すると Vim 以外もサポートしないといけない気になってしまう
単にモチベーションの問題
なので、今回はいち早く目的を達成するために nREPL クライアントという手段を取ったというのみで、Language Server にネガティブな気持ちがあるという訳ではありません。
最後に
vim-iced と CIDER は nREPL を通した協力関係にあるので、宗教に関係なく、裏から Clojure の開発環境改善に貢献していけたら良いなぁと思っています。
なお vim-iced は自分がぎょーむで使うために作ったもので、まだまだ自分に特化しています。
なので、いろいろな使い方をしてみてもらって意見がもらえたら嬉しいなぁと思ってます。