2024-02-14

Corfuの自動補完と手動補完で補完スタイルを変える方法

そもそも補完スタイルとは何かについてはマニュアルを参照するのが手っ取り早いでしょう(Completion Styles (GNU Emacs Manual)(日本語訳)。簡単に言えば先頭一致とか部分一致とか曖昧一致とかそういうのです。入力したテキストと補完候補が一致していることをどのように判定するかのルールです。例えば basic はほぼ先頭一致ですがカーソル(ポイント)を左に移動したときの挙動が追加されています(純粋な先頭一致は emacs21emacs22)。 substring はほぼ部分一致です。 flex は含まれている文字が順番に登場すれば一致と見なします。このようなルールを変数completion-stylesで指定します。複数指定出来るのは、マッチする候補があるスタイルを順に探していく仕組みになっているからです。

それで以前Corfuを導入したときに、私は自動補完と手動補完で補完候補のソースを変える設定をしました。

companyからcorfuへ移行~自動と手動で補完候補を変える | Misohena Blog

これは自動補完の時に確度の低い候補が出てきてキー入力を奪ってしまうことを回避するのが目的でした。自動補完の時は補完候補の大本を確度の高い物だけに限定してしまおうということです。

しかしそれだけでは不十分で、補完スタイル、つまり補完候補と入力テキストとのマッチング方法によっても実際に出現する候補は変わってきます。例えば補完スタイルにflexなどを指定してしまうと、非常に多くの補完候補とマッチングしてしまい、自動補完のポップアップが頻繁に出現することになりかねません。かといって、手動で補完するときはより沢山候補を出してほしい場合もあるでしょう。自動と手動で補完スタイルを切り替えたいのは当然ではないでしょうか。

というわけで、それを行うコードは次のようになります。

(defun my-corfu--auto-complete-deferred--change-completion-styles (old-fun &rest args)
  ;; corfu-autoの作用で補完候補を出すときに呼び出される
  (let (;; 自動補完の時に使う補完スタイル
        (completion-styles '(basic)))
    ;; 元の処理
    (apply old-fun args)))

(advice-add 'corfu--auto-complete-deferred :around #'my-corfu--auto-complete-deferred--change-completion-styles)

corfu--auto-complete-deferredは自動補完時にのみ呼び出される関数です。そこで一時的にcompletion-stylesをbasicのみにしてしまうと、入力したテキストと先頭一致する候補しか出てこなくなります。

これでひとまず目的は達成できたのですが、結局不意に現れた自動補完ポップアップによって誤操作してしまうという問題は相変わらず完全には解決できていません。自動補完で出す候補を少なくすることは確かに誤操作をする機会を減らしますが、一方で補完できる機会も減らしてしまいます。

そもそも自動補完というのは何が良いのでしょうか。別に補完がしたければ明示的にC-M-iと押せば補完できるのですからそれで良いはずです。しかしそれは補完できることをあらかじめ知っていなければできません。自動補完の良い所は、ユーザーが「こんな補完ができるのか」と気がつけるところにあるのです。そう考えたときに、別の方法を思いつきました。

(続く)