2021年の補完UI事情とEmacs28に標準添付されるfido-vertical-modeについて

メリークリスマス！ Emacs Advent Calendar 2021です！

今月頭にはGNU Emacsの次期安定版であるEmacs28のプレテスト版(いわゆるベータ版に相当)がリリースされました。いつもの通り？ならここからEmacs半年かからずにリリース候補版・正式版がリリースされるのではないでしょうか。Emacsの独特なバージョンのルールや過去のリリース履歴などは以下のページでご確認ください。

https://emacs-jp.github.io/tips/versions

さて、2021年のEmacs界隈を賑わしていたのが新しいミニバッファ補完UIの潮流でした。

各パッケージの位置付けや比較などは何人もの方が詳細な記事を書いてくださっているので参照ください。

 * [Emacsの次世代ミニバッファ補完UI | 日々、とんは語る。](https://blog.tomoya.dev/posts/a-new-wave-has-arrived-at-emacs/)
 * [君はselectrumとEmacsる？ - tsuu32](https://scrapbox.io/tsuu32/%E5%90%9B%E3%81%AFselectrum%E3%81%A8Emacs%E3%82%8B%EF%BC%9F)
 * [selectrum/consult/marginaliaの設定 - 備忘録](https://tam5917.hatenablog.com/entry/2021/04/29/235949)

まあざっくりまとめると、いままではHelm/Anythingのような補完フレームワークが以下のような機能をオールインワンで提供するような世界観でした。

 * ウィンドウ分割して項目を縦に並べるUI
 * 項目の絞り込み
 * アクション実行

https://qiita.com/tadsan/items/33ebb8db2271897a462b

新世代の補完機能は以下のような機能別のLispパッケージのどれかを選択、必要なものを組み合せて使うことで好みのものを利用できるようになっています。

 * ミニバッファを活用して項目を並べる補完UI
   * [icomplete](https://www.gnu.org/software/emacs/manual/html_node/emacs/Icomplete.html) (Emacs標準添付)
     * `fido-vertical-mode` (Emacs 28から追加)
   * [Selectrum](https://github.com/raxod502/selectrum) ([MELPA: selectrum](https://melpa.org/#/selectrum))
   * [vertico](https://github.com/minad/vertico) ([GNU ELPA: vertico](http://elpa.gnu.org/packages/vertico.html))
 * 選択候補の並び替え・マッチング (フィルタリング)
   * savehist-mode (Emacs標準添付)
      * シンプルな履歴保存機能
      * 参考: [emacs savehist: こんなの常識だよ？ミニバッファ履歴を保存する](http://emacs.rubikitch.com/savehist/)
   * [Orderless](https://github.com/oantolin/orderless) ([MELPA: orderless](https://melpa.org/#/orderless))
     * [補完スタイル](https://ayatakesi.github.io/emacs/25.1/Completion-Styles.html) + UI用のフィルタリング関数を提供
   * [prescient.el](https://github.com/raxod502/prescient.el)
     * prescient自体はシンプルなマッチングとソーティング、履歴の永続化(保存)
     * [selectrum-prescient](https://melpa.org/#/selectrum-prescient)、[ivy-prescient](https://melpa.org/#/ivy-prescient)のようなUI固有の拡張としての提供
 * 選択項目からのアクション起動
    * [Embark](https://github.com/oantolin/embark) ([MELPA: embark](https://melpa.org/#/embark))
 * 補完UIにリッチなメタ情報を付加
    * [Marginalia](https://github.com/minad/marginalia) ([GNU ELPA: marginalia](https://elpa.gnu.org/packages/marginalia.html))
 * 補完入力を活用した拡張コマンド
    * [Consult](https://github.com/minad/consult) ([GNU ELPA: consult](http://elpa.gnu.org/packages/consult.html))

これらのLispパッケージは極力Emacsの標準の拡張機構に準拠ないし標準機能のシンプルな置き換えとして提供されることで直交性が高く保たれていることが特徴です。

さて、いままでHelmのようなオールインワンパッケージで提供されていたものを個別に入れる必要が生じて複雑になったと捉えるべきか、使いたい機能だけ組み合わせて使えるようになって巨大パッケージから身軽になったと捉えるべきかは個々人の価値観によるところでしょう。ただ、[2020年には一時的にHelm開発者が開発終了を宣言する](https://www.reddit.com/r/emacs/comments/iskt2v/helm_github_repo_is_archived/)という事態も起こりました。多くの利用者がたった一人の開発者がメンテナンスしているパッケージに依存していた状況から、別々の開発者による単機能のパッケージまたはEmacs標準機能に分散されたのは喜ぶべきことだと考えます。

従来は発展的なパッケージはMELPAという非標準のパッケージリポジトリに投稿されていたものが、最近は上記パッケージを含む高品質で意欲的なパッケージが[GNU ELPA](https://elpa.gnu.org/)にも投稿されるようになったのも2021年の潮流だといえるでしょう。[GNU-devel ELPA Packages](https://elpa.gnu.org/devel/)からはMELPAのように正式リリース前の最新バージョンを取得することもできます。また、Emacs 28からは[NonGNU ELPA Packages](https://elpa.nongnu.org/nongnu/)が初期設定されており、Magitやphp-modeなどMELPAに依存していたパッケージも標準状態からインストールできるようにもなっています。

さて、ここまでが前置きでした。

https://blog.tomoya.dev/posts/a-new-wave-has-arrived-at-emacs/

先の @tomoyaton さんの記事には結びに以下のような文章があります。

> また、調べていく中でEmacs 28からはicomplete-vertical-modeというマイナーモードが標準で入ることを知りました。そのため、ミニバッファを縦に伸ばして補完するスタイルは、EmacsのスタンダードなUIになっていく可能性があります。

`icomplete.el`はEmacsの歴史ある入力補完UIでしたが、Emacs 22の頃に[IDO](https://www.gnu.org/software/emacs/manual/html_node/ido/index.html)が標準添付されるようになりました。ただしIDOがEmacsの標準補完UIとして置き換わることはなく、icompleteを完全に置き換えるには外部パッケージが必要など煮えきらない状態でした。

そんな中、Emacs 27ではicompleteでIDO風の操作を再現した`fido-mode`が、Emacs 28ではicompleteの補完を縦に並べる`icomplete-vertical-mode`が、そして両者が合体した**`fido-vertical-mode`**が爆誕しました。

https://www.manueluberti.eu/emacs/2021/08/06/fido/

お前を信じる俺を信じた！ 実際に使ってみましょう。Emacs 28がインストール済みならばVerticoからの移行はこれだけです。あくまでicompleteベースなのでIDOに対する`ido-ubiquitous`のような拡張パッケージの支援は要りません。

```diff:init.el
 (savehist-mode +1)
+(fido-vertical-mode +1)
-(leaf vertico :ensure t
-  :bind (:vertico-map (("C-l" . my-filename-upto-parent)))
-   :init
-  (vertico-mode +1))
 
 (leaf marginalia :ensure t
   :init
```

以下の表はMarginalia設定済みの自分の環境で`~/.emacs.d/init.el`を開いた状態で `C-x C-f`(find-file)を実行した状態のスクリーンショットです。

| mode | スクリーンショット |
|:----:|:------------:|
| fido-vertical-mode | ![スクリーンショット 2021-12-17 2.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4121/5eee4497-377a-560c-51d1-113d048eee19.png) |
| selectrum-mode | ![スクリーンショット 2021-12-17 2.57.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4121/d7b3c633-4a2d-560e-02b0-40b4df325623.png)| 
| vertico-mode | ![スクリーンショット 2021-12-17 2.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4121/7cbe6c64-e005-8604-84d0-5df7b3c1287d.png)|

https://dic.pixiv.net/a/%E5%85%A8%E9%83%A8%E5%90%8C%E3%81%98%E3%81%98%E3%82%83%E3%81%AA%E3%81%84%E3%81%A7%E3%81%99%E3%81%8B

~~「違いますよーっ」「これだからしろうとはダメだ！ もっとよく見ろ！」~~

絞り込みをしてない状態でのファイルの並び順がそれぞれ違うとか候補数の表示がちょっとずれてるとかの違いはありますが、見た目としてはほぼ同じですね……。

`icomplete-vertical-mode`の場合は候補が絞りきれない場合の確定方法にちょっと癖がある(参考: [icomplete-modeで入力を完了するためのコマンドをまとめる - Qiita](https://qiita.com/0x60df/items/e12544d2699eedbf36e1))のですが、他の補完UIに慣れている場合は`fido-vertical-mode`の方がしっくりくるのではないかと思います。

Vertico、Selectrum、そしてicompleteが独立して開発されているのは機能や微妙な使い勝手な違いなどがあるからなのですが、事ここに至っては自分のしっくりくるものを選ぶか、Emacsに標準添付された機能を尊重するかというところまで選択の自由が保証されているのは喜ばしいことです。また、トラブルシューティングでいつものEmacs設定が使えなくても`fido-vertical-mode`を有効にするだけで使い勝手のいいUIがすぐに使えるのは助かります。

今回の記事を書くにあたって気付いた問題として`icomplete-vertical-mode`は素性が`icomplete`だからなのか、ちょっとTABキーをつつくと別ウィンドウでディレクトリがポップアップしてしまうのが難点です。ちょっと調べれば抑制できる気もするし、正式リリース前に解決されるバグのような気もするのですが未解決です。何かわかったら教えてください。

この問題が理由ということはないですが、細かい操作感の好みとしてメインの環境ではもうしばらくVerticoを使い続けると思います。

## ついでにコードのインライン補完について

エディタで単に「補完」というと、一般的には編集中のプログラミング言語の構文や標準関数が編集中のバッファ内にあるキーワードなどが文脈に合わせてポップアップされ簡単に絞り込めるインターフェイスのことを指すと思うのですが、一般的なIDEのような入力補完のために[auto-complete](https://github.com/auto-complete/auto-complete)や[company-mode](http://company-mode.github.io/)のようなパッケージが利用されます。

Emacsが標準で提供する補完機能のauto-complete開発者の松山さんが[「Emacsのトラノマキ」連載第09回「auto-completeを使おう」(松山智大) | ありえるえりあ](http://dev.ariel-networks.com/wp/documents/aritcles/emacs/part9/)に書かれた記事のスクリーンショットにあるようにウィンドウ分割による補完が基本でした。

これまで紹介してきたVertico, Marginalia, Consultを開発しているminadさんが[Corfu](https://github.com/minad/corfu)というパッケージを開発しており、Emacs標準の補完メカニズム(`completion-at-point-functions`, **capfs**)が利用できるようになっているようです。こちらに関してはまだ語れるほどよく知らないので、既に使いこなしている誰かが紹介してくれるでしょう、きっと……！