* Modern Completion Stack

I'm using modern to mean current, and as the colloquial usage given by the
community at large.  At least based on my observations anyway.  Most of these
serve to bolster the existing facilities of emacs rather than replace them.

** Prescient

[[https://github.com/radian-software/prescient.el][Prescient]] provides sorting for completion candidates; So recently used, and
frequent selections come first.

#+begin_src emacs-lisp
(use-package prescient
  :defer t
  :config
  (prescient-persist-mode))

(use-package corfu-prescient
  :after (corfu prescient)
  :config (corfu-prescient-mode))

(use-package vertico-prescient
  :after (prescient vertico))
#+end_src

** Corfu

[[https://github.com/minad/corfu][Corfu]] provides completion within buffers from various sources.  Though it
doesn't provide much in the way of sources itself.  It works in conjunction
with the other packages in this section to provide it with candidates.

#+begin_src emacs-lisp
(use-package corfu
  :custom
  (corfu-auto t)               ;; Enable auto completion
  (corfu-preselect 'directory) ;; Select the first candidate, except for directories

  :init
  (global-corfu-mode)
  (corfu-popupinfo-mode) ;; Show docs next to candidates.

  :config
  ;; Free the RET key for less intrusive behavior.
  ;; Option 1: Unbind RET completely
  ;; (keymap-unset corfu-map "RET")
  ;; Option 2: Use RET only in shell modes
  (keymap-set corfu-map "RET" `( menu-item "" nil :filter
                                 ,(lambda (&optional _)
                                    (and (derived-mode-p 'eshell-mode 'comint-mode)
                                         #'corfu-send)))))
#+end_src

** Cape

The [[https://github.com/minad/cape][Cape]] package (Completion At Point Extensions) provides access to [[https://github.com/minad/corfu][Corfu]]
to various backends.  Things like file completions and simple buffer
completion are examples of good backends to add here.  Other backends
are listed [[https://github.com/minad/cape#available-capfs][here]].

#+begin_src emacs-lisp
(use-package cape
  :bind ("M-<tab>" . cape-prefix-map)
  :init
  (add-hook 'completion-at-point-functions #'cape-dabbrev)
  (add-hook 'completion-at-point-functions #'cape-file)
  (add-hook 'completion-at-point-functions #'cape-elisp-block))
#+end_src

** Orderless

This provides numerous flexible methods for matching completion candidates.
Rather than just matching strings exactly it can also match portions, or
a custom regular expression, and more.

[[https://stable.melpa.org/#/orderless][Link]]

#+begin_src emacs-lisp
(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles partial-completion)))))
#+end_src

** Vertico

[[https://github.com/minad/vertico][Vertico]] is one of the *best* minibuffer improvement packages out there.  Combined
with the other packages in this section it makes minibuffer completions concise,
and descriptive.

#+begin_src emacs-lisp
(use-package vertico
  :demand t
  :custom (vertico-cycle t)
  :config
  (setf (car vertico-multiline) "\n") ;; don't replace newlines
  (vertico-mode)
  (vertico-prescient-mode)
  (define-key vertico-map (kbd "C-h") #'+minibuffer-up-dir))
#+end_src

** Marginalia

[[https://github.com/minad/marginalia][Marginalia]] adds completion annotations on the right side of the minibuffer.

#+begin_src emacs-lisp
(use-package marginalia
  :defer 2
  :config (marginalia-mode)
  (setf (alist-get 'elpaca-info marginalia-command-categories) 'elpaca))
#+end_src

** Consult

#+begin_quote
[[https://github.com/minad/consult][Consult]] provides search and navigation commands based on the emacs completion
function completing-read.
#+end_quote

Think about this as a tightly integrated search that can tie into many aspects
of a project, and convey the results to various completion facilities.

#+begin_src emacs-lisp
(use-package consult
  :ensure t
  :bind (;; C-c bindings in `mode-specific-map'
         ("C-c M-x" . consult-mode-command)
         ("C-c h" . consult-history)
         ("C-c k" . consult-kmacro)
         ("C-c m" . consult-man)
         ("C-c i" . consult-info)
         ([remap Info-search] . consult-info)
         ;; C-x bindings in `ctl-x-map'
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
         ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ("C-x t b" . consult-buffer-other-tab)    ;; orig. switch-to-buffer-other-tab
         ("C-x r b" . consult-bookmark)            ;; orig. bookmark-jump
         ("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ;; M-g bindings in `goto-map'
         ("M-g e" . consult-compile-error)
         ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
         ("M-g m" . consult-mark)
         ("M-g k" . consult-global-mark)
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings in `search-map'
         ("M-s d" . consult-find)                  ;; Alternative: consult-fd
         ("M-s c" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l" . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
         ;; Minibuffer history
         :map minibuffer-local-map
         ("M-s" . consult-history)                 ;; orig. next-matching-history-element
         ("M-r" . consult-history))                ;; orig. previous-matching-history-element

  ;; Enable automatic preview at point in the *Completions* buffer. This is
  ;; relevant when you use the default completion UI.
  :hook (completion-list-mode . consult-preview-at-point-mode)

  ;; The :init configuration is always executed (Not lazy)
  :init

  ;; Tweak the register preview for `consult-register-load',
  ;; `consult-register-store' and the built-in commands.  This improves the
  ;; register formatting, adds thin separator lines, register sorting and hides
  ;; the window mode line.
  (advice-add #'register-preview :override #'consult-register-window)  (setq register-preview-delay 0.5)

  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)

  ;; Configure other variables and modes in the :config section,
  ;; after lazily loading the package.
  :config

  ;; Optionally configure preview. The default value
  ;; is 'any, such that any key triggers the preview.
  ;; (setq consult-preview-key 'any)
  ;; (setq consult-preview-key "M-.")
  ;; (setq consult-preview-key '("S-<down>" "S-<up>"))
  ;; For some commands and buffer sources it is useful to configure the
  ;; :preview-key on a per-command basis using the `consult-customize' macro.
  (consult-customize
   consult-theme :preview-key '(:debounce 0.2 any)
   consult-ripgrep consult-git-grep consult-grep consult-man
   consult-bookmark consult-recent-file consult-xref
   ;; :preview-key "M-."
   :preview-key '(:debounce 0.4 any))

  ;; Optionally configure the narrowing key.
  ;; Both < and C-+ work reasonably well.
  (setq consult-narrow-key "<") ;; "C-+"

  ;; Optionally make narrowing help available in the minibuffer.
  ;; You may want to use `embark-prefix-help-command' or which-key instead.
  ;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help)
  )
#+end_src

