🖤

Vimmer から見た Emacs ファジーファインダーの歴史について

2023/03/25に公開

始めに

Emacs ファジーファインダーフレームワークの歴史

私はこれまでいくつかのファジーファインダーを開発してきました。それは Emacs のプラグイン anything.el にとても影響を受けています。
anything.el が存在しなければ私がプラグイン開発をすることもなかった。そういえるほどです。
anything.el のリリースからとても長い月日が経ちました。Vim 界でのファジーファインダーのトレンドが急速に移り変わっているように、Emacs 界隈でもファジーファインダーのトレンドが移り変わっています。ここは私の視点で Emacs 界隈のその歴史を振り返ってみることにしましょう。

anything.el 2007 年頃開発開始

ファジーファインダーの歴史は明確に anything.el 以前と anything.el 以後に分かれます。
現在のテキストエディタではファジーファインダーを使うのは普通になっていますが
anything.el はテキストエディタにファジーファインダーという文化を導入した立役者といっても過言ではないでしょう。

https://github.com/emacs-jp/anything

anything.el

ちなみに、私の開発したファジーファインダーである unite.vim がどれだけ anything.el に影響を受けているかは以下の資料を参照してください。

https://gist.github.com/Shougo/7fc95389ab6fddac7f78deb6ce42e82a

anything.el の配布は Emacs-jp のリポジトリで行われているようですが、開発はされてないようです(2023 年 3 月現在)。

helm.el 2012 年頃開発開始

anything.el の機能が一通り開発された後、anything.el は破壊的変更を行わない長い安定期に入りました。
anything.el の共同メンテナの一人が anything.el をドラスティックに拡張するために anything.el を fork して開発されたのが helm.el です。

https://github.com/emacs-helm/helm

参考: http://emacs.rubikitch.com/sd1503-helm/

helm.el の開発はとても盛んなのですが、あまりにドラスティックに変更が行われるので、ユーザーが付いていけなくなり離れてしまっている印象があります。

helm.el は独自の思想が強く、デフォルトのキーマッピングが Emacs 標準と離れていたりするようです。作者が自分の独自設定をプラグインデフォルトにしているようなものなのでしょう。

helm.el の欠点として、巨大すぎるのでカスタマイズが困難であることが挙げられます。基本的には helm.el の流儀に従う必要があります。
これだけで Emacs のディストリビューションプラグインみたいなもので、必要な機能のみ有効化したりシンプルな機能が好きな人には向きません。

anything.elhelm.el には persistent action というものがあります。これはアクション実行後にファジーファインダーを閉じない特別なアクションを定義するもので、 候補一つにつき一種類しか定義できないようです。
ddu.vim だと preview アクションや no quit なアクションに相当しますが、ddu.vim の場合は複数のアクションを定義可能です。

ちなみに、昔ほどではないですが今でも helm.el の開発自体は続いています(2023 年 3 月現在)。

counsel.el 2013 年頃開発開始、話題になったのは 2019〜2020 年

counsel.elivy.el, swiper.el を用いてファジーファインダーを実装したものです。
元々は swiper.el というバッファ検索するプラグインだったようなのですが、counsel.el により汎用的なファジーファインダーとして利用できるようになったようです。
github のリポジトリ名にも歴史的経緯が表れています。

https://github.com/abo-abo/swiper

counsel.el は機能が分割されており、以下のように役割が分かれています。

  • ivy.el: 補完フレームワーク。

  • swiper.el: Isearch を利用したバッファ検索。ivy.el に依存。

  • counsel.el: ファジーファインダー用の便利コマンドを定義したもの(sources に相当)。swiper.el に依存。

それぞれが本来機能として独立しているのですが、全てのプラグインが一つのリポジトリで配布されているのは欠点といえます。

counsel.elivy.el は既存のプラグインを拡張したという歴史的経緯により、その実装はとても複雑なものになっているようです。

参考: https://github.com/radian-software/selectrum#ivy

単一の巨大フレームワークとしてではなく、複数のプラグインを組み合わせてファジーファインダーを実現しているのは、後の vertico.el にも繋がる考え方であり興味深いといえるでしょう。

counsel.el がよく使われるようになった背景ですが、helm.el のメンテナが helm.el の開発終了を宣言したり(現在は撤回?)したことや、重厚長大でカスタマイズが困難な helm.el よりシンプルで仕様が安定したものがよいとユーザーが移行した結果にあるようです。

ちなみに counsel.el の開発は停滞しているように見えます(2023 年 3 月現在)。

vertico.el 2021 年頃開発開始

vertico.elswiper.el とは異なり外部のフレームワークプラグインを利用しないファジーファインダーです。
フレームワークプラグインを利用せずにどうやって機能を実現するのかですが、Emacs の標準機能を用いています。
Emacs の標準機能をカスタマイズすることで、ファジーファインダーとして動作しているというのは素直にすごいです。

https://github.com/minad/vertico/

vertico.el は Emacs の標準機能を用いて Emacs の UI そのものをカスタマイズしているので、専用のコマンドを使わなくても UI が vertico.el になるという利点があるようです。
これは neovim における noice.nvim のような UI カスタマイズプラグインに相当する概念でしょう。

vertico.el は高速であるらしく、速度を理由に counsel.el から移行した人がいます。

https://macowners.club/posts/from-ivy-to-vertico/

vertico.el はカスタマイズの柔軟性も魅力です。コマンド毎に挙動をカスタマイズできるようです。

vertico.el でファジーファインダーを実現する場合は、以下のように単一機能を持つ複数のプラグインをユーザーが組み合わせて使用します。

  • Emacs 標準 API((completing-read) 等): ファジーファインダーフレームワーク。

  • vertico.el: ミニバッファを用いたファジーファインダー UI。

  • consult.el: コマンドの提供、候補リストの作成。

  • marginalia.el: 付加情報の表示。

  • orderless.el: マッチ方法を変更し、スペース区切りで入力をマッチさせる。

  • embark.el: アクションを実行する。

これだと Vimmer には分かりにくいかもしれないので ddu.vim の各種機能で表現すると、以下のようになります。

  • Emacs 標準 API((completing-read) 等): ddu.vim 相当。

  • vertico.el: UI 相当。

  • consult.el: source と ddu-commands.vim 相当。

  • marginalia.el: converter や column 相当。

  • orderless.el: filter 相当。

  • embark.el: kind 相当。

従来のファジーファインダーだと一つのパッケージと必要ならば追加の source をインストールするだけでよかったのに、vertico.el では単一の機能しかないので、多数のプラグインをインストールする必要があります。

なぜこのようなややこしい作りになっているのかは、ddu.vim でなぜ機能が分割されたのかと理由は同じだと考えられます。
特定のプラグインに機能を依存せず、簡単に機能を交換可能にするためです。

現在は上記のようにプラグインの定番の組み合わせが存在しますが、これは絶対ではありません。違うプラグインを好きに組み合わせることができるし、気にいらなければあなたが別のものを作ることが可能なのです。「ユーザーに選択の自由が与えられている」、これが重要なのです。
その代わり、ユーザーは「自分がなにをしているのか」を知る必要があります。フレームワークに全てを任せる時代は終わりを告げています。

vertico.el の欠点もいくつかあるようです。consult.el がサポートしている機能は他のファジーファインダーと比較すると貧弱であること、同期 source と非同期 source を混ぜることが困難であること(同期 source のみ混ぜられる)、複数候補の選択をサポートしていないことです。

従来の anything.el, helm.el, counsel.el はどれも重厚長大なフレームワークでした。
それらに依存することの欠点をユーザーは知ってしまったのでしょう。Emacs の標準機能に依存すれば外部のフレームワークが必要なくなるし、Emacs の標準機能の開発が停滞することはありません。Emacs 標準機能は安定していて、よくテストされています。

ちなみに、同じことを Vim で実装するのは難しいです。Vim には標準で Emacs ほどの UI の拡張性はないからです。
neovim だとプラグインによる UI カスタマイズが一部可能ですがまだ不安定です。

Discussion