エンジニアリングの世界には、特定の技術領域を10年、20年といった単位で極め続け、圧倒的な影響力を誇るスペシャリストが存在します。テキストエディタVimの世界において、まさにその代表格と言えるのがShougoさんです。
2008年ごろから開発の第一線に立ち、neocomplcache.vim、unite.vim、deoplete.nvim、そして近年ではddc.vimやddu.vimなど、Vimのユーザー体験を劇的に進化させるプラグインを数多く世に送り出してきました。
Shougoさんはなぜ飽きることなく、15年以上にわたりテキストエディタの探求を続けられるのでしょうか。スペシャリストの思想と歩みを伺いました。
「自分でゼロから作ろう」開発の原点はEmacsへの憧れ
― Shougoさんは、2008年ごろからVimのプラグイン開発を始めたと伺っています。そもそも、なぜプラグインを自作するようになったのでしょうか?
「ほしいものが世の中になかったから」ですね。当時はちょうどVim 7.0がリリースされたばかりの時期で、Vimプラグインという文化そのものが黎明期にありました。既存のプラグインは、正直に言って使い物にならないと感じるものが多かったです。
たとえば、当時のVimにも自動補完プラグインはありましたが、それは単にVimの組み込み機能(Ctrl-XやCtrl-Nなど)を自動で呼び出すだけの単純なものでした。これでは本体の仕様に縛られてしまい、それ以上の拡張ができませんでした。
一方、当時のEmacsはすでに拡張機能が発展していましたが、中でもanything.elやauto-complete.elの登場は非常に画期的でした。何がすごかったかというと、それらが単なる便利機能ではなく「フレームワーク」だった点です。ベースとなる機能があり、その上にユーザーが自分たちで拡張を載せていける。その自由度の高さに衝撃を受けました。
私がEmacsの拡張機能に見たような「フレームワークとしての柔軟性」を、なんとかしてVimでも実現したい。そのためには、既存のものを改良するよりも、自分でゼロから作ったほうが早いと考えたのが、自作の道を選んだ原点ですね。
― どのような技術を用いて、プラグインを開発してきたのですか?
最初は、ほぼVim scriptしか選択肢がありませんでした。しかし、機能を次々と追加してコードが数万、数十万行という規模になったころ、大きな問題に直面しました。Vim scriptはもともと、巨大なシステムをつくるために設計された言語ではありません。そのため、パフォーマンスは悪化しバグも頻発するという、いかんともしがたい状況になってしまいました。
Lua、Python、そしてDeno。技術基盤の変遷と試行錯誤
― 技術面で大変な思いをされたのですね。
そこで、他の選択肢はないかと模索し始め、まず取り組んだのが「一部の処理のLua化」でした。ボトルネックとなる重い処理だけをLuaに任せて、高速化しようと試みたんです。
とはいえ、今でこそNeovimの影響でLuaは一般的ですが、当時はLua拡張を使っている人などほとんどいない時代でした。プラグインに組み込んだところ、Vim本体のバグがたびたび発生して大変でしたね。開発元に修正を依頼しながら進めるような状態で、かなり苦労しました。
― Luaを導入したことで、開発のつらさは解消されたのでしょうか?
パフォーマンスはある程度改善しましたが、「Vim scriptで巨大なプラグインをつくるのは大変」という根本的な問題は解決しませんでした。むしろ、言語が混在することでデバッグがさらに難しくなるという側面もありました。
そんな時に登場したのがNeovimであり、その目玉機能の一つである「リモートプラグイン」でした。これはVim本体と外部プロセスを通信させて拡張機能をつくる仕組みです。私はこの機能を用いることにし、外部プロセスの言語としてPythonを選びました。
これならVim scriptのコードを最小限に抑えられますし、Pythonなら開発もしやすいだろうと考えたんです。後からVimでも動くようにラッパーも整備されたので、これでVimとNeovimの両対応ができる、完成形だと思っていました。ところが、今度は「Pythonの実行環境」という別の困難が待っていたんです。
― Pythonでの開発において、何が問題だったのですか?
Pythonという言語自体は素晴らしいのですが、ユーザー側の環境に依存しすぎる点が非常に厄介でした。実行ファイルの場所や参照しているライブラリ、インストールされているパッケージの差異などによって、プラグインの挙動や動作の安定性が変わってきます。
このあたり、Pythonで書かれたWebシステムを動かす場合には、システムのPythonではなく自前でPythonを用意する必要がある、つまり環境を隔離する必要があることからも察することができます。Pythonは広く使われているがゆえに簡単にコンフリクトするのです。
ユーザーから報告されるエラーの大部分が、Python環境に起因するものでした。Pythonでの開発体験は悪くなかったのですが、これを一般のユーザーに使ってもらうのはサポート面で限界がある、と痛感しました。
― そこで次の選択肢を探すことになったのですね。
はい。当時は「Luaで丸ごと書き直す」ことも考えましたが、それだとNeovimでしか動かないプラグインになってしまいます。VimとNeovimではLuaのAPIが異なるからです。
私は、どちらか片方だけをサポートする方針があまり好きではありません。VimとNeovim、双方の内部コードを理解しているからこそ、両方で同じように動くものをつくる。それが自分の強みであり、譲れないプライドでした。
そんな折に登場したのが、Denoを活用するdenops.vimという技術でした。これなら、VimとNeovimの両方で同じように動作させることができます。
― Denoに移行してみて、手応えはいかがですか?
非常にいいですね。Denoは実行ファイルのインストールが容易で、ライブラリ管理も非常にクリーンです。そして、TypeScriptという型のある言語で開発できるのも快適です。何より、あらゆる環境で安定して動いてくれることは、大規模なプラグインをメンテナンスし続ける上で、はかり知れない利点になっています。
denopsの唯一の欠点は、Deno起動までのオーバーヘッドでしょうか。ただ、これはPythonリモートプラグインの場合も同じだったので悪化したわけではありません。ちなみに、このオーバーヘッドを嫌い、未だにunite.vimを使う人もいるようです……。
ShougoさんはVimConf 2024の「The latest dark deno powered plugins」でも、Deno(TypeScript)を用いて開発したプラグインの詳細について触れている。
「多機能であることをやめた」たどり着いた疎結合の哲学
― 採用する技術以外に、昔と今とで設計思想が変わった部分はありますか?
かつては「多機能であること」を重視していたのですが、それをやめました。以前はEmacsへの憧れもあり、ユーザーからの要望にできる限り応えたいという思いがありました。ですが、それらをすべて取り込んでいった結果、プラグインがどんどん肥大化していったんです。
特に厄介だったのが、補完ソースなどの機能を本体に同梱していたことでした。必要なものが最初から何でも入っていれば、インストールしてすぐに使えるので便利です。しかしその一方で、ユーザーにとっては「使わない機能まで全部ついてくる」という状態になりますし、開発側としては責任の所在が曖昧になるという大きな問題がありました。
― 責任の所在が曖昧になる、とは具体的にどういうことでしょうか?
たとえば、私のリポジトリに不具合報告や要望が来たとき、それが「フレームワーク本体の問題」なのか、それとも「組み込みの補完ソースの問題」なのかが判別しづらくなり、管理が非常に煩雑になってしまったんです。
この問題は他のプラグインでもよく起こっています。特にユーザーの数が膨大になると、issueの量が爆発しますし大変です。そのため徐々に、「フレームワークが持つ責務のみに専念し、それ以外の機能とは独立させるべきではないか」と考えるようになりました。
もちろん、機能を同梱することには「ユーザーにとってインストールが楽」「本体の仕様変更にすぐ追従でき、互換性を保ちやすい」といった利点もあります。しかし、自分のプラグインにおいて、それらは本当に必要な利点なのかを改めて問い直したんです。
― その結果、どのような結論に至ったのですか?
まず「インストールが楽」という点ですが、もともと私のプラグインは非常に多機能で、ユーザーが自分の好みに合わせて設定しないと真価を発揮できない設計です。どうせユーザーに機能の選択や設定をお願いするのなら、導入の手間だけを減らしても利点はそれほど大きくありません。
また「互換性」についても、ユーザーが自作の拡張機能を作れるようにしている以上、そもそも本体側のAPIを安易に壊してはいけません。どのみち、第三者がつくるプラグインのために互換性を守り続ける必要があるのなら、自作の機能を「本体の一部」として特別扱いするのと、「外部モジュール」として扱うのとでは、メンテナンスの手間は実質的に変わりません。
そうであれば、あえて本体に同梱し続ける理由はなく、むしろ疎結合であることの利点を追求すべきだという結論に達しました。この設計思想が明確に固まったのは、Denops世代であるddc.vimやddu.vimなどからですね。自分のプラグインが果たすべき役割が、より明確になっていきました。
デフォルトのキーバインドはいらない。すべてをユーザーが決めるべき
― 設計思想において、他に変化はありますか?
プラグイン側で、デフォルトのキーバインドを設けない方針にしました。これも先ほどの「余分な機能を同梱しない」という話と、根底は同じです。
機能が増えると、「どの機能をどのキーに割り当てるか」という問題が常に付きまといます。新しい機能を足すたびに既存のマッピングと競合しないか悩み、一度決めたものを変更しようとすれば互換性の問題が生じる。これは開発者にとって非常に大きなコストです。
また、ユーザーによって使いやすいキーは千差万別です。私自身、他の方のプラグインを使うときは、まずデフォルトのマッピングを無効化して自分好みに書き換えるところから始めます。そうした経験から、「そもそもデフォルトのキーバインドなんて、最初から用意しなくていいのでは?」と思うようになりました。
仮にデフォルト設定があれば、インストールしてすぐに使えるという利点はあります。でも、あえて私のプラグインを選ぶようなユーザーであれば、ドキュメントを読み、自分でマッピングを定義することに抵抗はないはずです。
― すべてを自分で設定しなければならないというのは、初心者にはハードルが高そうです。そこについてはどうお考えですか?
そう感じる方は、他のエディタやプラグインを使えばいいと思います。便利なツールは世の中にたくさんありますから。
確かに、設定をゼロから組み上げるのは時間がかかりますし、学習コストも高いかもしれません。でも、Vimを使っている人たちにとって、エディタを自分好みにカスタマイズすること自体が一つの楽しみであるはずです。設定そのものが楽しいのであれば、それは「作業」ではなく「娯楽」に変わりますよね。
このエピソードに関連した余談ですが、私のプラグインを使っている方々の中には「設定させてもらってありがとうございます」という趣旨のことをおっしゃる方もいるそうです(笑)。ちょっと過激な思想ではありますが、そう言っていただけるのは開発者冥利に尽きますね。
AI時代、テキストエディタはより重要になる
― 膨大な数のプラグインを、長年にわたって一人でメンテナンスし続けるための秘訣はありますか?
うーん、特にはありません。テキストエディタに飽きたことがないですから。むしろ、他の方々がなぜそんなに簡単にテキストエディタという分野に飽きてしまうのか、不思議に思っているくらいです(笑)。
― テキストエディタが、長年取り組んでいても飽きない、探究しがいのある領域だということでしょうか?
そうです。そして、テキストエディタに限らず、どんな領域であっても探究のしがいはあると思うんです。そもそもテキストエディタの技術は、世の中の影響を受けて変化し続けます。テキストエディタのトレンドを追っている限り、飽きるとは考えづらいです。テキストエディタを追うのが面倒になった、というのならわかりますが。
― 最近では、AIがコードを書く時代になっています。もしかしたら、「エディタはなんでもいい」と考える方もいるかもしれません。そんな時代に、エディタを自分好みに徹底的にカスタマイズし続けることには、どのような意義があるとお考えですか?
AIが普及しても、「人間がコードを読み書きすること」の重要性は変わらないと思います。ほとんどの方は、AIが書いたコードをチェックし、修正要望や動作確認を経て、問題がなければ取り込むというプロセスで作業をしますよね。
これは私にとっては、OSSのリポジトリに届いたPull Requestをレビューするプロセスとほぼ変わりません。そして、人間が自力でコードを理解できなければ、コードを書いたのが人間であるかAIであるかにかかわらず、問題のあるコードを取り込んでしまうことになり、システムはあっという間にカオスになります。
だからこそ、エディタを通じてコードと向き合う重要性はこれからも変わりませんし、自分が最高のパフォーマンスを発揮できるように道具を改善し続けることには、大きな意義があると考えています。

