corfuまわりの設定(vertico, marginalia, orderless, cape, kind-icon, affe)

corfuおよび関連するパッケージの設定をメモとして残す。

  • corfu ... companyパッケージの代わり。カーソル位置での補完UIを提供。
  • vertico ... ido-vertical-modeやivy, selectrumの代わり。ウィンドウ下部(ミニバッファ)で垂直表示な補完UIを提供。
  • consult ... counselの代わり。補完入力を活用し、他のコマンドをラップした便利なコマンド群を提供。
  • marginalia ... consultに表示される候補に「補助情報」を追加する(ファイル属性、ファイル更新日、ファイルサイズなど)。
  • orderless ... 補完候補の絞り込みに活躍。「イニシャル入力」などにより高速かつ柔軟な候補絞り込みを実現。
  • cape ... corfuとの組み合わせが前提。カーソル位置での補完対象が拡張される。
  • kind-icon ... corfu/orderlessと相性の良いパッケージ。各候補の左側に「アイコン」(SVG形式)が追加される。
  • affe ... fuzzy-matchingなconsult-grepやconsult-findに相当するコマンドを提供する。

embarkは割愛。

以下、ほぼ公式の設定を参考にしたもの。verticoについてはvertico-directoryも使う。すごく便利なので。

;; -*- mode: emacs-lisp; coding: utf-8-unix -*-

(require 'corfu)
(corfu-global-mode)
(setq corfu-cycle t) ;; 候補ウィンドウの移動において、上端/下端に達したら下端/上端に回り込む
(setq corfu-auto t) ;; 補完を自動で開始
(setq corfu-quit-no-match 'separator)
(setq corfu-quit-at-boundary nil)

;; 候補スクロール開始位置が、候補ウィンドウの下から何行目か
(setq corfu-scroll-margin 2)

;; ミニバッファでの補完を有効にする
(defun corfu-enable-always-in-minibuffer ()
  "Enable Corfu in the minibuffer if Vertico/Mct are not active."
  (unless (or (bound-and-true-p mct--active)
              (bound-and-true-p vertico--input))
    ;; (setq-local corfu-auto nil) Enable/disable auto completion
    (corfu-mode 1)))
(add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1)

;; TAB cycle if there are only few candidates
(setq completion-cycle-threshold 3)

(defun corfu-beginning-of-prompt ()
  "Move to beginning of completion input."
  (interactive)
  (corfu--goto -1)
  (goto-char (car completion-in-region--data)))

(defun corfu-end-of-prompt ()
  "Move to end of completion input."
  (interactive)
  (corfu--goto -1)
  (goto-char (cadr completion-in-region--data)))

(define-key corfu-map [remap move-beginning-of-line] #'corfu-beginning-of-prompt)
(define-key corfu-map [remap move-end-of-line] #'corfu-end-of-prompt)

(require 'vertico)
(vertico-mode)
(setq vertico-count 20)

(require 'vertico-directory)
(define-key vertico-map (kbd "C-l") #'vertico-directory-up)
(define-key vertico-map "\r" #'vertico-directory-enter)  ;; enter dired
(define-key vertico-map "\d" #'vertico-directory-delete-char)

(require 'marginalia)
(marginalia-mode +1)
;; marginalia-annotatorsをサイクルする
(define-key minibuffer-local-map (kbd "C-M-a") #'marginalia-cycle)

(require 'orderless)
(setq completion-styles '(orderless))

(orderless-define-completion-style orderless+initialism
  (orderless-matching-styles '(orderless-initialism ;;一番最初にinitializm
                               orderless-literal  ;;次にリテラルマッチ
                               orderless-regexp)))

;; (setq completion-category-defaults nil)
(setq completion-category-overrides
      '((eglot (styles orderless+initialism))
        (command (styles orderless+initialism))
        (symbol (styles orderless+initialism))
        (variable (styles orderless+initialism))))
(setq orderless-component-separator #'orderless-escapable-split-on-space)

(require 'cape)
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-tex)
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-keyword)
(add-to-list 'completion-at-point-functions #'cape-abbrev)
(add-to-list 'completion-at-point-functions #'cape-ispell)
(add-to-list 'completion-at-point-functions #'cape-symbol)

;; EmacsのSVG対応コンパイルが必要
(require 'kind-icon)
(setq kind-icon-default-face 'corfu-default)
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter)

;; Available commands
;; affe-grep: Filters the content of all text files in the current directory
;; affe-find: Filters the file paths of all files in the current directory
(require 'affe)
(consult-customize affe-grep :preview-key (kbd "M-."))
(defvar affe-orderless-regexp "")
(defun affe-orderless-regexp-compiler (input _type)
  (setq affe-orderless-regexp (orderless-pattern-compiler input))
  (cons affe-orderless-regexp
        (lambda (str) (orderless--highlight affe-orderless-regexp str))))
(setq affe-regexp-compiler #'affe-orderless-regexp-compiler)