Switching to Corfu

I switched to using Corfu as my in-buffer completion framework this afternoon.

I've never been happy about my Company configuration, so when I read Corfu's README it just sounded like it is for me.

Corfu uses child frames by default — I haven't had good results with child frames, but so far with Corfu it seems to work just fine. I also have a need to use Emacs in a terminal (in Termux), which corfu-terminal solves pretty easily.

So far I'm pretty happy about how it feels. I also know I don't really have to worry about a lack of backend support — which is why I don't use FlyMake — because cape-company-to-capf provides support for Company backends.

TL;DR (I'm using leaf, which is basically a leaner use-package):

(dolist (pkg '((corfu :type git :host github
                      :repo "emacs-straight/corfu"
                      ;; The default recipe doesn't put extensions into `load-path'.
                      ;;
                      ;; This is also a thing with Vertoco. It's annoying.
                      :files ("*" "extensions/*.el" (:exclude ".git")))
               ;; `corfu-terminal''s dependency. Right now straight.el does not
               ;; support NonGNU ELPA, so this has to be installed separately.
               (popon
                :type git
                :repo "https://codeberg.org/akib/emacs-popon.git")
               (corfu-terminal
                :type git
                :repo "https://codeberg.org/akib/emacs-corfu-terminal.git")
               cape
               kind-icon
               company
               company-glsl
               company-shell))
  (straight-use-package pkg))

(leaf corfu
  :init
  (setq corfu-auto t
        corfu-quit-no-match t
        corfu-quit-at-boundary 'separator)
  (global-corfu-mode)
  :config
  (define-key corfu-map
    (kbd "SPC") #'corfu-insert-separator)
  (setq completion-cycle-threshold 3)
  ;; Use Corfu in `eval-expression' and other commands that bind
  ;; `completion-at-point' in the minibuffer.
  ;;
  ;; WHY IS THIS NOT AVAILABLE IN AN OPTION IF IT'S ALREADY LISTED IN
  ;; THE README
  (add-hook 'minibuffer-setup-hook (lambda ()
                                     (when (memq #'completion-at-point
                                                 (flatten-tree
                                                  (current-local-map)))
                                       (corfu-mode))))
  (leaf cape
    ;; Available: cape-file cape-dabbrev cape-history cape-keyword
    ;; cape-tex cape-sgml cape-rfc1345 cape-abbrev cape-ispell
    ;; cape-dict cape-symbol cape-line
    :init
    (add-hook 'completion-at-point-functions #'cape-file)
    (add-hook 'completion-at-point-functions #'cape-dabbrev 90)
    (add-hook 'prog-mode-hook
              (lambda ()
                (add-hook 'completion-at-point-functions
                          #'cape-keyword nil t)))
    :config
    (require 'company)
    (cl-loop for backend in '(company-glsl company-shell company-ledger)
             do (add-hook 'completion-at-point-functions
                          (cape-company-to-capf backend))))
  (leaf kind-icon
    :after corfu
    :require t
    :config
    (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
  (leaf corfu-terminal
    :after corfu
    :require t
    :init (corfu-terminal-mode))
  (leaf corfu-history
    :after corfu
    :config
    (with-eval-after-load 'safehist
      (cl-pushnew 'corfu-history savehist-additional-variables))
    (corfu-history-mode)))