fido-vertical-modeの設定あれこれ

久しぶりに .emacs.d (Emacsの設定)を新たに書き直しています。

(かなり)重い腰を上げた理由は、新しいMacBookに切り替えたこととか、ふとEmacs 27から29に上げたらEmacs環境が壊れたこととかいろいろあるのですが、設定をモダンにやり切るところまでやろうと思ったのは、やはり @takeokunn からの突き上げ?がvim-jpラジオでピークに達したことが理由です*1

audee.jp

audee.jp

最初は「今の設定が動くところまで」だけで終わっていたんですけどね。

最後の最後にvim-jpラジオを聴いて「やるかああああああああ」となりました。上記のエピソードはEmacserにとてもオススメです。やる気にさせてくれます*2

やはり道具としてのEmacs、使い込まないといけないですね*3

20252021年最新のEmacsの設定

さて、何がモダンなEmacsの設定なのかというと、2021年の記事ですが以下がとてもわかりやすいです。信頼できる筋のエントリなので信頼できます。

blog.tomoya.dev

今時のEmacserには普通なんだと思いますが、私は2024年までHelm / Companyで止まっていましたからね。隔世の感があります。

ようは

  • Emacsの標準の機能を駆使する
  • 小さなパッケージを組み合わせる

というのがトレンドのようです。

Vertico、Consult、Corfu、Orderless、Marginalia、Embark らへんが、主力っぽいです。

よーし、だんだんわかってきた。

fido-vertical-modeを使う

さらに、確かな信頼できる筋のエントリを見てみます。これも2021年。

qiita.com

Emacs 28から fido-vertical-mode というVerticoっぽいマイナーモードが、Emacs標準で提供されたそうです。

で、

「”Emacsの標準の機能を駆使する”のがトレンドなら、Verticoよりもfido-vertical-modeを使ったほうが良いのではないか」

という安直な動機で、fido-vertical-mode を使うことにしました。

(fido-vertical-mode +1) ;; 設定はこれだけ。便利。

が、

どうやらまだ時代はVerticoのようで、fido-vertical-modeの設定例があまりなく、少し困ったので、いくつか設定を共有します。

補完のためのミニバッファの領域を大きくしたい

Anything/Helm時代、私は補完候補を大きく画面の半分に出して使うスタイルだったのですが、初期設定だとConsult(+ fido-vertical-mode)で補完候補を出しても、画面の1/4程度しか出してくれません。

Verticoであれば vertico-count で設定できるっぽいのですが、fido-vertical-mode に fido-vertical-count はありません。

じゃあどうすればいいのか。ということで icomplete.el*4ソースコードを見に行ったらそれらしい記述がありました。

As many completion candidates as possible are displayed, depending on the value of max-mini-window-height', and the way the mini-window is resized depends onresize-mini-windows'.

emacs/lisp/icomplete.el at 6a299b3caceb2c73b932ba73849738faa8c5d975 · emacs-mirror/emacs · GitHub *5

さらに設定例までありました。なるほど。

(add-hook 'icomplete-minibuffer-setup-hook (lambda () (setq-local max-mini-window-height 3)))

will constrain Emacs to a maximum minibuffer height of 3 lines when icompletion is occurring.

emacs/lisp/icomplete.el at 6a299b3caceb2c73b932ba73849738faa8c5d975 · emacs-mirror/emacs · GitHub

というわけで、私は画面の半分(50%)まで表示させたいので小数点以下の値を使って以下のように設定しました。

(add-hook 'icomplete-minibuffer-setup-hook
          (lambda ()
            (setq-local max-mini-window-height 0.5)))

なお、max-mini-window-height自然数を設定すると表示画面割合ではなく表示行数になります。便利。

補完スタイル( completion-styles )にOrderlessを使いたい

www.gnu.org

補完スタイル(主に補完候補の絞り込みのスタイル)をOrderlessをはじめとする便利なスタイルに切り替えるのが良いとのことなので以下のように設定してみましたがうまく補完スタイルがデフォルトから変更されません。

(fido-vertical-mode +1)

;; Consult
(use-package consult
  :ensure t
  :hook (completion-list-mode . consult-preview-at-point-mode))

;; Orderless
(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))

また icomplete.el のソースを見にいくと、fido-vertical-mode( fido-mode )の起動タイミングで completion-stylesflex に上書き設定されていることがわかりました( icomplete--fido-mode-setup 関数)。

emacs/lisp/icomplete.el at 6a299b3caceb2c73b932ba73849738faa8c5d975 · emacs-mirror/emacs · GitHub

icomplete--fido-mode-setup 関数は minibuffer-setup-hook にフックされているっぽいので、発火タイミングを調整しながら、さらに completion-styles を上書き設定するようにしました。

;; Orderless
(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion))))
  :config
  (remove-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup)
  (add-hook 'minibuffer-setup-hook ;; <- icomplete--fido-mode-setup より後に発火させる
            (lambda ()
              (setq-local completion-styles '(orderless basic))))
  (add-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup))

なお、 orderless doesn't work with fido · Issue #110 · oantolin/orderless · GitHub でも同じようなワークアラウンドが紹介されていました。

もう少しスッキリ書きたかったのですが、今のElisp力ではここまで

2025/1/14 10:28追記

早速有識者からアドバイスをいただきました。ブログ書いて良かった。

;; Orderless
(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion))))
  :config
  (add-hook 'minibuffer-setup-hook
            (lambda ()
              (setq-local completion-styles '(orderless basic)) t))

スッキリ!

Orderlessのスペース区切りと相性が悪いのをなんとかしたい(2025/1/14 15:17追記)

vim-jp Slackの #tech-emacs チャンネルで、fido-vertical-modeを使っているとスペース入力でワード補完が走ることがあり、それがOrderlessの「スペース区切りでの補完キーワード列挙」の機能と相性が悪いというのを教えていただきました。

設定時は気づいていなかったのですが、確かにスペースでワード補完が走ってしまうことある*6ことがわかりました。

ソースを追ってみると minibuffer.el のkeymapとバッティングしていることがわかりました。

emacs/lisp/minibuffer.el at e6ad99e36c6c2e5322381f8af48cc283d2d899dc · emacs-mirror/emacs · GitHub

ということで無効化します。

;; Orderless
(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion))))
  :config
  (keymap-unset minibuffer-local-completion-map "SPC") ;; for using with fido-vertical-mode
  (add-hook 'minibuffer-setup-hook
            (lambda ()
              (setq-local completion-styles '(orderless partial-completion))) t))

なお、最近は define-key global-set-key ではなく keymap-set keymap-global-set を使うらしいです(これも #tech-emacs チャンネルで教えてもらいました)。

naokton.hatenablog.com

今のところ fido-vertical-mode で十分満足

Verticoを使ったことがないのでアレなんですが、今のところ fido-vertical-mode で十分満足しています。Marginaliaもちゃんと連携できますし。 「Emacsの標準の機能を駆使する」という意味ならまあ良い選択なのではないかなと。

有識者のアドバイスお待ちしております。

*1:今までも会うたびに、むしろ最初に会った時からずっと、「Emacsの設定をモダンにしろ」と言われ続けていました。いつも最新のEmacs事情が聞けて楽しい。

*2:主にEmacs

*3:ラジオでの@tadsanの発言より

*4:fido-modeは誕生の経緯からicomplete.elにあるようです

*5:簡単のため、このエントリではソースコードへのリンクをGitHubにある非公式のミラーリポジトリに貼っています。ref: https://www.reddit.com/r/emacs/comments/4bg3b6/what_is_the_emacs_github_mirror_for/

*6:たぶん https://github.com/emacs-mirror/emacs/blob/e6ad99e36c6c2e5322381f8af48cc283d2d899dc/lisp/minibuffer.el#L4826-L4828C25 らへん