6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CorfuのREADME

Last updated at Posted at 2025-02-14

GNU Emacs

GNU ELPA

GNU-devel ELPA

MELPA

MELPA Stable


Table of Contents


Corfuは小さな補完ポップアップでバッファー内補完(in-buffer completion)を強化するパッケージだ。カレント候補はポイント位置の下か上にポップアップ表示、上下に移動して選択することができる。CorfuはミニバッファーUIであるVerticoと対をなす、ミニマリズム指向のバッファー内補完である。

Corfuは補完はEmacsの補完機能に任せて、洗練された補完UIの提供に専念した小さなパッケージだ。Emacsではバッファー内補完UIはcompletion-in-region(ユーザーとの相互作用を実装している)にフックを仕掛けることができる。ポイント位置での補完はdabbrev-completionのようなコマンドや、取り外し可能なバックエンド(completion-at-point-functions: 以下Capfsと略)が提供して、その後にcompletion-in-regionに渡されるのだ。Capfsはプログラミング用、テキスト用、シェル用といったメジャーモードの多くで実装されているCorfu自体には補完バックエンドは含まれていない。EmacsビルトインのCapfsと、サードパーティ製のプログラミング言語パッケージが提供するCapfsで間に合うことが多いのだ。追加のCapfsおよび補完ユーティリティはCapeパッケージで別途提供している。

注意: Corfuのポップアップの表示は子フレーム(child frame)に依存している。Emacs 31では端末モードのEmacsでも子フレームがサポートされる筈だ。それより前のバージョンのEmacsでもcorfu-terminalパッケージを使えるだろう。

機能

  • タイマーに基づいた自動補完(デフォルトでは オフ )

  • インジケーターつきスクロールバーと矢印キーでのナビゲーションができるポップアップ表示

  • TAB押下によりいつでも明示的にポップアップを召喚可能

  • カレント候補の挿入はTAB、選択はRET

  • プレフィックス、文字列長、アルファベット順にソート可能(通常はヒストリー順)

  • 選択された候補のプレビュー(corfu-preview-currentで設定可)

  • デフォルトでは候補選択によりそれ以上の入力は自動省略(corfu-preview-currentで設定可)

  • 補完スタイルOrderlessをサポート。 M-SPC(corfu-quit-at-boundarycorfu-separatorで設定可)の挿入後は、フィルター文字列に任意の文字を含められる。

  • 性能に配慮した補完の遅延ハイライト

  • 補完への注釈(annotation)のサポート(annotation-functionaffixation-function)

  • 鮮度が失われるにつれ候補を抹消

  • marginフォーマット関数経由のサードパーティパッケージ提供のアイコンをサポート

  • インデックスキー、ヒストリー順のソート、エコーエリア、ポップアップ、別バッファーでの候補ドキュメント参照

インストール

CorfuはGNU ELPAから入手できる。M-x package-install RET corfu RETで直接インストールすることも可能だ。インストール後にM-x global-corfu-mode RETでグローバルマイナーモードをアクティブにすればよい。バッファーでM-TAB(やTAB)を翁すれば補完できるだろう。安全と慎みの観点より自動補完はデフォルトでは無効になっている。

キーバインディング

Corfuは一時的なキーマップ(keymap)としてcorfu-mapを使用する。このキーマップはポップアップが表示されている間はアクティブになる。以下の基本的なコマンドやバインディングのリマップ(remap: 再マップ)は、このキーマップで定義されているのだ:

バインディング/リマップ Corfuのコマンド
move-beginning-of-line corfu-prompt-beginning
move-end-of-line corfu-prompt-end
beginning-of-buffer corfu-first
end-of-buffer corfu-last
scroll-down-command corfu-scroll-down
scroll-up-command corfu-scroll-up
next-linedownM-n corfu-next
previous-lineupM-p corfu-previous
completion-at-pointTAB corfu-complete
M-TAB corfu-expand
RET corfu-insert
M-g corfu-info-location
M-h corfu-info-documentation
M-SPC corfu-insert-separator
C-g corfu-quit
keyboard-escape-quit corfu-reset

コンフィグ

あなたはuse-packageを使って、"init.el"でCorfuと他のパッケージを設定したいと思うかもしれない。カスタマイズ用の変数corfu-*を通じて、あなたの要件に正確に適合するようにCorfuを柔軟にカスタマイズできる筈だ。しかしCorfuの補完パッケージを手早く試すだけなら、global-corfu-modeをアクティブにすれば十分だろう。たとえばElispバッファーやEshell、あるいはシェルバッファーで手動で補完を経験できる。

Corfuでは自動リンクはデフォルトでは無効になっている。補完がもつ信用できないファイルの任意のコードを実行できる能力は、脆弱性となり得ることに注意して欲しい。特にマクロ展開とコードの評価を行う補完関数elisp-completion-at-pointには注意が必要だ。ローカルでのcorfu-mode、あるいはグローバルにglobal-corfu-modeを有効にする前にcorfu-autotをセットすれば、自動補完が有効になる。以下はコンフィグの例:

    (use-package corfu
      ;; オプションのカスタマイズ
      ;; :custom
      ;; (corfu-cycle t)                ;; `corfu-next/previous'による巡回を有効にする
      ;; (corfu-quit-at-boundary nil)   ;; 補完境界で終了しない
      ;; (corfu-quit-no-match nil)      ;; マッチがなくても終了しない
      ;; (corfu-preview-current nil)    ;; 候補のプレビューを無効にする
      ;; (corfu-preselect 'prompt)      ;; プロンプトでの事前選択
      ;; (corfu-on-exact-match nil)     ;; 正確なマッチの取り扱い設定
    
      ;; 特定モードでのみCorfuを有効化(`global-corfu-modes'も参照されたい)
      ;; :hook ((prog-mode . corfu-mode)
      ;;        (shell-mode . corfu-mode)
      ;;        (eshell-mode . corfu-mode))
    
      ;; お勧め: Corfuをグローバルに有効化
      ;; Dabbrevがグローバルに使用可になるのでお勧め
      ;; 特定モードの除外はカスタマイズ変数`global-corfu-modes'を参照のこと
      :init
      (global-corfu-mode))
    
    ;; 更に便利なコンフィグをいくつか...
    (use-package emacs
      :custom
      ;; 候補が少なければTABで巡回
      ;; (completion-cycle-threshold 3)
    
      ;; インデントと補完の両方にTABキーを使える機能を有効化
      ;; `completion-at-point'はM-TABにバインドされていることが多い
      (tab-always-indent 'complete)
    
      ;; Emacs 30以降: Ispellの補完関数を無効化
      ;; かわりに`cape-dict'を試してみて欲しい
      (text-mode-ispell-word-completion nil)
    
      ;; カレントモードには適用されないコマンドはM-xで表示しない
      ;; CorfuコマンドはM-x経由で使用されることはないので非表示になる
      ;; これはCorfuに限らず役に立つセッティングだろう
      (read-extended-command-predicate #'command-completion-default-include-p))

completion-in-regionを基本とするDabbrevはCorfuでも使用可能だ。展開よりも補完の方が好みであれば、簡単にアクセスできるようにdabbrev-completiondabbrev-expandを交換したいと思うかもしれない。わたしのCapeパッケージが提供する、ポイント位置用の補完関数cape-dabbrevも試してみて欲しい。

    ;; Corfuと一緒にDabbrevを使う!
    (use-package dabbrev
      ;; M-/とC-M-/を交換
      :bind (("M-/" . dabbrev-completion)
             ("C-M-/" . dabbrev-expand))
      :config
      (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ")
      ;; 29.1以前は古い`dabbrev-ignored-buffer-regexps'を使用すること
      (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode)
      (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)
      (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode))

より徹底したCorfu設定を始める場合には、フィルタリングに補完スタイルOrderlessを試すことをお勧めする。Orderlessの補完はデフォルトの補完スタイルい比べてより柔軟なフィルタリングを提供する。Orderlessが必要という訳ではないことに注意。デフォルトの補完スタイルでも、同じようにCorfuは使用できるのだ。

    ;; オプションで補完スタイル`orderless'を使用する
    (use-package orderless
      :custom
      ;; (orderless-style-dispatchers '(orderless-affix-dispatch))
      ;; (orderless-component-separator #'orderless-escapable-split-on-space)
      (completion-styles '(orderless basic))
      (completion-category-defaults nil)
      (completion-category-overrides '((file (styles partial-completion)))))

orderlessに加えてフォールバックとして補完スタイルbasicを指定しているが、これは動的補完テーブル(completion-table-dynamiccompletion-table-in-turn)に依存する補完コマンドの、正しい動作を保証するためだ。ファイルパスの展開用に追加でpartial-completionも有効にしている。ファイルでのワイルドカードをサポートするのであればpartial-completionは重要だ。find-fileでワイルドカードを入力すれば、複数ファイルを一度にオープンできる。補完スタイルinitialsを試してみるのもよいだろう。

Capf用の追加コンフィグのヒントについてはCorfu WikiCape manualにもあるので参考にして欲しい。より一般的な文書については、Emacs manualの補完のチャプターを読むとよいだろう。独自のCapfsを作成したい場合には、Elisp manualで補完に関する文書が見つかる筈だ。

自動補完

安全性と慎みの観点から、自動補完はデフォルトでは無効になっている。任意のコードを実行できるという能力から、補完が脆弱性となり得ることに注意して欲しい。corfu-autotをセットすれば自動補完は有効にできる。自動補完は信頼できるバッファーでのみローカルに有効にするか、グローバルに有効にする場合には信頼できるファイルだけを編集しているときに限定する必要がある。

意図せず補完がポップアップして作業の邪魔になるような場合には、補完をさっさと閉じるようにCorfuを設定したいだろう。

    ;; 自動補完を有効化するとともに補完終了を設定
    (setq corfu-auto t
          corfu-quit-no-match 'separator) ;; またはt

あなたにとって満足できるセッティングが見つかるまで、さまざまなセッティングやキーバインディングを体験してみることをお勧めする。すべてを満足するような完璧な設定など存在しない。自動補完を好む人もいれば手動補完を好む人、TABで巡回したい人や矢印キーで巡回したい人もいるのだから。

補完が即座にポップアップする自動補完セッティングがお好みならば、basic(プレフィックスによりフィルタリングを行う)のような低コストの補完スタイルを使用する方がよいだろう。Corfuに限定した補完スタイルのセッティングについては次のセクションで説明しよう。このような場合には、効率的な補完バックエンドと組み合わせれば、バッファー内補完のCorfuの方が依然として高速な筈だ。ElispバッファーやEmacsのscratchバッファーで以下のセッティングを試してみることができる。この種のセッティングは高負荷なLispの実行時ロードとガベージコレクションにより、Emacs全体の速度が低下する恐れがあることに注意。

    (setq corfu-auto        t
          corfu-auto-delay  0  ;; 小さすぎ - 非推奨!
          corfu-auto-prefix 0) ;; 小さすぎ - 非推奨!
    
    (add-hook 'corfu-mode-hook
              (lambda ()
                ;; Corfuだけのセッティング
                (setq-local completion-styles '(basic)
                            completion-category-overrides nil
                            completion-category-defaults nil)))

バッファーローカルな補完スタイルやCorfuのみの補完スタイル

ミニバッファー用の補完とバッファー内のCorfu補完用に、補完スタイルを個別に使い分けられた方がよい場合がある。たとえば高速なプレフィックス補完が必要だったりリテラルの補完だけで十分な場合にはCorfu、ミニバッファーの中では高度なOrderless補完を使いたい場合だ。

これは補完が即座にポップアップ表示される積極的(aggressive)なセッティングでは特に影響があるだろう。そのような場合にはプレフィックスによるフィルタリングしか行わない、basicのような低コストの補完スタイルを使用するべきだ。

このようなCorfuだけのコンフィグは、バッファーローカルに変数completion-stylesを設定することで実現できるだろう。

    (orderless-define-completion-style orderless-literal-only
      (orderless-style-dispatchers nil)
      (orderless-matching-styles '(orderless-literal)))
    
    (add-hook 'corfu-mode-hook
              (lambda ()
                (setq-local completion-styles '(orderless-literal-only basic)
                            completion-category-overrides nil
                            completion-category-defaults nil)))

高速なプレフィックスによるフィルタリングとOrderlessのフィルタリングを組み合わせたい場合には、まだorderless-define-completion-styleを通じてOrderlessの補完スタイルをカスタム定義するという手が残されている。4文字よりも短い入力にたいして効率的なプレフィックスフィルタリングを有効にする、カスタムのスタイルディスパッチャを使うことにしよう。

    (defun orderless-fast-dispatch (word index total)
      (and (= index 0) (= total 1) (length< word 4)
           (cons 'orderless-literal-prefix word)))
    
    (orderless-define-completion-style orderless-fast
      (orderless-style-dispatchers '(orderless-fast-dispatch))
      (orderless-matching-styles '(orderless-literal orderless-regexp)))
    
    (setq corfu-auto        t
          corfu-auto-delay  0  ;; 小さすぎ - 非推奨!
          corfu-auto-prefix 0) ;; 小さすぎ - 非推奨!
    
    (add-hook 'corfu-mode-hook
              (lambda ()
                (setq-local completion-styles '(orderless-fast basic)
                            completion-category-overrides nil
                            completion-category-defaults nil)))

ミニバッファーでの補完

Corfuの候補表示は子フレーム頼りである。それ故に逆にミニバッファーの補完にCorfuを使用することができることになる。CorfuのポップアップはEmacsの最上位フレームにフローティング表示されるので、ミニバッファー内部に収まらなくても表示が可能なのだ。

変数global-corfu-minibufferが非nilの場合には、global-corfu-modeをアクティブにすることでミニバッファーでcorfu-modeもアクティブになる。VerticoやMctのようにミニバッファーに特化した補完UIと干渉しないように、ミニバッファーで変数completion-at-point-functionsがローカルにセットされた場合のみCorfuが有効化される仕組みだ。この方法なら補完付きのミニバッファーを検知できるので、M-: (eval-expression)やM-! (shell-command)のようなコマンドをCorfuの補完で補強できる筈だ。

必要ならより一般的に、アクティブな補完UIがなくなるまでCorfuをすべてのミニバッファーで有効にすることもできる。以下の例では、MctとVerticoをチェックする述語関数としてglobal-corfu-minibufferをセットしている。更にミニバッファーからの読み取ったのがパスワードの場合には、確実にCorfuが無効になるようにしてみよう。

    (setq global-corfu-minibuffer
          (lambda ()
            (not (or (bound-and-true-p mct--active)
                     (bound-and-true-p vertico--input)
                     (eq (current-local-map) read-passwd-map)))))

EshellやShellでの補完

Eshellで行う際には自動補完なしにすることをお勧めする。広く使われているBash、Zsh、あるいはFishと同じような、控え目な振る舞いになるようなローカルセッティングにしよう。

    (add-hook 'eshell-mode-hook (lambda ()
                                  (setq-local corfu-auto nil)
                                  (corfu-mode)))

Corfuのポップアップ表示中にRETを押下すると、corfu-insertコマンドが呼び出される筈だ。これはカレントで選択された候補を挿入するコマンドだが、EshellやCominitのプロセスにプロンプトの入力を送信しない。したがって2回の押下が必要なことがよくある。この二重確認は不要に思える。幸いcorfu-sendコマンドをかわりに使えば、これは簡単に改善できるのだ。

    (keymap-set corfu-map "RET" #'corfu-send)

シェル補完が内部的に使用しているのは、柔軟なPcompleteメカニズムである。これはシェルコマンドごとにプログラミング可能な補完だ。より詳細について知りたければ、blog postを調べて欲しい。この記事ではgitコマンド用のPcomplete設定にも触れている。Emacsの29以降のPcompleteはコマンドにたいして--helpを渡したときの出力を解析して、コマンドラインオプションに使用できる補完を生成できる。

Emacs 28以前のPcompleteにはバグがいくつか存在する。この問題はCapeライブラリー(ポイント位置補完の拡張)で解決できるだろう。Capeが提供するのはPcomplete関数を消毒するためのラッパーだ。Emacs 29では関係のあるほとんどのバグは修正されたので、adviceはもう不要な筈だ。まだ残っているPcompleteの問題を見つけたら、どうかアップストリームに報告していただきたい。

    ;; `pcomplete-completions-at-point'(以降Capfと略)を消毒
    ;; このCapfにはEmacs 28以前では望ましくない副作用があった
    ;; Emacs 29以降ではこれらのadviceは不要になった
    (when (< emacs-major-version 29)
      (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
      (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify))

Orderlessの補完

Orderlessがサポートしているのは、設定可能な文字(デフォルトではスペース)で区切られた、マルチコンポーネントの検索フィルターという補完スタイルだ。通常は補完リージョンの境界外にあるスペースのような文字を入力することで、Corfuは終了する。これは自動補完では役に立つ挙動だろう。たとえば新たな変数名をタイプしたときは意図せずポップアップするかもしれない。それでもタイプを続行すれば、Corfuのポップアップは消えるだろうから。

しかしOrderlessの検索には特定の任意な文字を含めることができ、それらは正規表現としても解釈されるのだ。Orderlessを使用するには、corfu-separatorにOrderlessの主要なコンポーネント区切り(デフォルトはスペース)をセットする。

そうすれば新たなOrderlessコンポーネントが必要になったら、M-SPC (corfu-insert-separator)を使って1つ目のコンポーネントの区切りを入力する。その後にOrderlessの任意の検索用語を続けて、また新たな区切りを入力するといった具合に使用するのだ。

入力全体をOrderlessの入力として扱わせたい場合にはカスタマイズ用のオプションcorfu-quit-at-boundarynilをセットすればよい。これはカレントの補完境界が残っていないかどうかチェックする述語を無効にするオプションだ。反対に常に境界で終了させたい場合には、corfu-quit-at-boundarytをセットすればよいだろう。デフォルトではcorfu-quit-at-boundaryseparatorにセットされている。これはcorfu-insert-separatorで区切りが入力されないかぎりは、補完境界で終了するオプションだ。

最後にcorfu-quit-no-match(デフォルトはseparator)というユーザーオプションがある。このセッティングなら、corfu-separatorで高度な検索を開始したCorfuは、たとえばタイプの間違え等のせいでマッチがなくてもそのまま生き残る筈だ。しかしcorfu-insert-separatorで区切り文字を挿入した場合には、マッチがなければ終了する挙動は変わらない。これにより補完が不可能なら、Corfuが速やかにポップアップを消すことが保証されるのだ。

以下に2つのコンフィグを紹介しよう。1つ目は自動補完においてベストなコンフィグ、もう1つはOrderless補完の区切りに常にSPCを使いたい場合には上手く機能しそうなコンフィグだ。

    ;; 自動補完の例
    (use-package corfu
      :custom
      (corfu-auto t)          ;; 自動補完を有効化
      ;; (corfu-separator ?_) ;; スペース以外の区切りを使うならセット
      :bind
      ;; S-SPCのように別のキーにバインドしてもよい
      ;; (:map corfu-map ("M-SPC" . corfu-insert-separator))
      :init
      (global-corfu-mode))
    
    ;; 手動補完の例
    (use-package corfu
      :custom
      ;; (corfu-separator ?_) ;; Orderlessの区切りにスペース以外を使うならセット
      :bind
      ;; SPCで区切る設定
      (:map corfu-map ("SPC" . corfu-insert-separator))
      :init
      (global-corfu-mode))

TABのみの補完

デフォルトではCorfuがポップアップをオープン中には、RETTABの両方のキーをCorfuが横取りする。これは特に自動補完と組み合わせた場合には、差し出がましく感じるかもしれない。実際には改行したいのに、自動選択された候補をRETで間違えてコミットしてしまう恐れもあるだろう。

corfu-mapからRETを完全にバインド解除したり、シェルモードでのみ複数アイテム用のフィルターで用いるようにRETを予約するという別の手もある

    ;; TABだけの設定
    (use-package corfu
      :custom
      (corfu-auto t)               ;; 自動補完を有効化
      (corfu-preselect 'directory) ;; ディレクトリー以外は最初の候補を選択
    
      :init
      (global-corfu-mode)
    
      :config
      ;; RETキーの開放で少し慎ましく
      ;; Option 1: RETのバインドを完全に解除
      ;; (keymap-unset corfu-map "RET")
      ;; Option 2: シェルモードのみRETを使用する
      (keymap-set corfu-map "RET" `( menu-item "" nil :filter
                                     ,(lambda (&optional _)
                                        (and (derived-mode-p 'eshell-mode 'comint-mode)
                                             #'corfu-send)))))

TAB-and-Go補完

TAB-and-GoスタイルでCorfuを設定することに興味があるだろうか。TABの押下で次の候補へ移動、更に押下すると選択が確定するのだ。スニペットの展開を強制するには、RETで明示的に候補を選ぶようにしよう。

    (use-package corfu
      ;; TAB-and-Goの設定画面
      :custom
      (corfu-cycle t)           ;; `corfu-next/previous'での巡回を有効化
      (corfu-preselect 'prompt) ;; プロンプトは常に自動選択
    
      ;; TAB(デフォルトは`corfu-complete'だった)は巡回に使用
      :bind
      (:map corfu-map
            ("TAB" . corfu-next)
            ([tab] . corfu-next)
            ("S-TAB" . corfu-previous)
            ([backtab] . corfu-previous))
    
      :init
      (global-corfu-mode))

補完のミニバッファーへの転送

より豪華な対話機能を提供するミニバッファーに、Corfuの補完セッションを転送すると役に立つ場合もあるのではないだろうか。特にミニバッファーではEmbarkが利用できるのだ。候補にアクションを適用したり、候補を別のバッファーにエクスポートしたり収集することができるだろう。直接エクスポートや収集ができるEmbarkのサポートは、近い将来Corfuに追加されるだろう。とはいえCorfuの補完をミニバッファーに転送できれば更に強力になる筈だ。ミニバッファーでのさらなる補完が可能になるからだ。

ここでコマンドcorfu-move-to-minibufferは、(completing-readを通じてミニバッファー補完を使用する)consult-completion-in-regionの観点で定義してある。

    (defun corfu-move-to-minibuffer ()
      (interactive)
      (pcase completion-in-region--data
        (`(,beg ,end ,table ,pred ,extras)
         (let ((completion-extra-properties extras)
               completion-cycle-threshold completion-cycling)
           (consult-completion-in-region beg end table pred)))))
    (keymap-set corfu-map "M-m" #'corfu-move-to-minibuffer)
    (add-to-list 'corfu-continue-commands #'corfu-move-to-minibuffer)

拡張

このレポジトリのサブディレクトリーextensions/には、わたしたちが保守している小さな拡張パッケージがある。ELPAからパッケージをインストールしたのなら、Corfuと一緒に拡張もインストールされている筈だ。拡張はデフォルトではアクティブになっていないが、アクティブにしたいなら手動で有効にできる。更にcorfu.elcorfu-*.el両方の拡張ファイルは、すべて個別にインストール可能だ。ELPAのCorfuパッケージには、現在のところ以下の拡張が同梱されている:

  • corfu-echo: corfu-echo-modeはエコーエリアに補完の要約ドキュメントを表示する

  • corfu-history: corfu-history-modeは選択した候補を覚えておいて、候補のヒストリー上の位置で候補をソートする

  • corfu-indexed: corfu-indexed-modeはインデックス付けした候補をプレフィックスで選ぶようにできる

  • corfu-info:候補の位置やドキュメントにアクセスするためのアクション

  • corfu-popupinfo: 補完メニュー隣りに候補のドキュメントとソースをポップアップ表示

  • corfu-quick: Avyスタイルのクイックキーを用いた選択コマンド

コンフィグの詳細は、これらのファイルのコメントを参照して欲しい。

補足的なパッケージ

Corfuはcompletion-at-point-functionsを通じたコード補完を提供するすべてのパッケージと良好に動作する筈だ。インストールしただけで使用できるCapfを、すでに多くのモードやパッケージが提供している。とはいえセットアップの改善に、補足的なパッケージについても知っておきたいのではないだろうか。

  • corfu-candidate-overlay: タイプするにしたがい、多くの候補の中に目指す候補が存在するのかを視覚的に示す補完オーバーレイを表示する(corfu-autoが無効な場合のみ機能する)。

  • corfu-terminal: Emacs 31からはデフォルトで端末の子フレームがサポートされる。それより古いバージョンのEmacsにたいしてオーバーレイベースのポップアップ表示を提供するパッケージだ。

  • Orderless: Corfuがサポートしている補完スタイルには、orderlessの上級向けな補完スタイルが含まれている(スペースあるいは別の文字でフィルター式を区切れる; corfu-separatorを参照)

  • Cape: 追加のCapfバックエンドとcompletion-in-regionを提供する。他のパッケージと異なるのはファイル補完バックエンドのcape-file、そしてDabbrevバックエンドのcape-dabbrevを提供する点だ。更にCapeはCorfuでCompanyのバックエンドを再利用する際のアダプターとなるcape-company-to-capfも提供している。

  • kind-iconおよびnerd-icons-corfu: Corfuでは外部パッケージを通じてアイコンをサポートしている。kind-iconがサポートするのはモノクロのアイコンセットに基づくSVGであることに比べて、nerd-icons-corfuは端末さえもサポートするNerdアイコンを基にしたパッケージだ。

  • Tempel: Lisp構文のテンプレートでテンプレート/スニペットを提供する小さなパッケージ。Corfuと組み合わせて使用可能。

  • Vertico: わたしのVerticoパッケージにも興味があるかもしれない。VerticoはCorfuと対を成すミニバッファー補完を提供する。

他の選択肢

.
  • Company: Companyは広く使われている成熟した補完パッケージであり、Corfuと似たUIを実装している。Corfuは専らEmacsの標準補完API(Capfs)に頼っているが、Companyはバックエンド用に独自にAPIを定義している。Companyには自身の独自APIにしたがう独自の補完バックエンドがあるがこれはEmacsの補完インストラクチャーとは互換性がないのだ。CompanyはCompanyのバックエンドとしてCapfsを処理するアダプターを提供している。このデザインの結果、CompanyはCorfuに比べてより複雑であり、バックエンドを除外してもおよそ3倍のサイズがある。またCorfuではポップアップに子フレームを用いるが、Companyはデフォルトではポップアップにオーバーレイを使用する点も対照的だろう。いずれのパッケージも全体としては良好に動作するが、Emacsとの統合の度合いという点においてはCompanyが若干劣っている。completion-stylesのサポートはより制限されており、コマンドcompletion-at-pointおよび関数completion-in-regionはCompanyを呼び出さないのだ。
  • consult-completion-in-region: Consultパッケージはconsult-completion-in-regionという関数を提供している。completion-in-region-functionにこの関数をセットすれば、completion-at-pointの処理を任せることができる。この関数はバッファー内の補完をミニバッファーに転送することによって機能する。ミニバッファーにおいてはたとえばVerticoがミニバッファー用の補完UIとして使用されるだろう。補完はすべてミニバッファーで行いたければ、consult-completion-in-regionが最善のオプションだ。

Corfuのデバッグ

もしあなたがポストコマンドフックcorfu--post-commandでエラーを発見したら、デバッグを強制するためにadviceをインストールする必要がある。これによりエラー位置を絞り込むためのスタックトレースが入手できる筈だ。これはEmacsによってポストコマンドフックが自動的に無効にされる(そしてデバッグされない)せいだ。さもないとすべてのコマンドの後にこのフックが実行されてしまい、Emacsが使い物にならなくなってしまうだろう。

    (setq debug-on-error t)
    
    (defun force-debug (func &rest args)
      (condition-case e
          (apply func args)
        ((debug error) (signal (car e) (cdr e)))))
    
    (advice-add #'corfu--post-command :around #'force-debug)

思ったようにCapfsの結果が得られない場合には、Capfへのデバッグメッセージ追加にcape-capf-debugを付かうことができるだろう。。そうすればCapfが補完ログをmessageバッファーに出力する筈だ

    (setq completion-at-point-functions (list (cape-capf-debug #'cape-dict)))

Capfs内部のクラッシュを目にするかもしれないことに注意。そのような問題は修正しなければならないバグがそのCapfsに存在するということだ。このようなCapfsはCorfuで使うことはできない。

貢献について

このパッケージはGNU ELPAの一部なので、貢献にはFSFへの著作権譲渡が必要ないとなる。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?