February 23, 2024 · (updated August 5, 2024) · 13 min · 2735 words · Kristian Alexander P
Vertico provides a performant and minimalistic vertical completion UI based on the default completion system. The focus of Vertico is to provide a UI which behaves correctly under all circumstances. By reusing the built-in facilities system, Vertico achieves full compatibility with built-in Emacs completion commands and completion tables. Vertico only provides the completion UI but aims to be highly flexible, extendable and modular. Additional enhancements are available as extensions or complementary packages. The code base is small and maintainable. The main vertico.el package is only about 600 lines of code without white space and comments1.
;; Enable vertico(use-packagevertico:init(vertico-mode);; Different scroll margin;; (setq vertico-scroll-margin 0);; Show more candidates;; (setq vertico-count 20);; Grow and shrink the Vertico minibuffer;; (setq vertico-resize t);; Optionally enable cycling for `vertico-next' and `vertico-previous'.;; (setq vertico-cycle t));; Persist history over Emacs restarts. Vertico sorts by history position.(use-packagesavehist:init(savehist-mode));; A few more useful configurations...(use-packageemacs:init;; Add prompt indicator to `completing-read-multiple'.;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.(defuncrm-indicator(args)(cons(format"[CRM%s] %s"(replace-regexp-in-string"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'"""crm-separator)(carargs))(cdrargs)))(advice-add#'completing-read-multiple:filter-args#'crm-indicator);; Do not allow the cursor in the minibuffer prompt(setqminibuffer-prompt-properties'(read-onlytcursor-intangibletfaceminibuffer-prompt))(add-hook'minibuffer-setup-hook#'cursor-intangible-mode);; Emacs 28: Hide commands in M-x which do not work in the current mode.;; Vertico commands are hidden in normal buffers.(setqread-extended-command-predicate#'command-completion-default-include-p);; Enable recursive minibuffers(setqenable-recursive-minibufferst))
Commands for Ido-like directory navigation. The commands can be bound in the vertico-map. Furthermore a cleanup function for shadowed file paths is provided.
Suspend the current Vertico completion session. If vertico-suspend is called from within the currently active Vertico minibuffer, the completion session is suspended. Otherwise the last session is restored. It is possible to suspend multiple nested Vertico sessions. Note that vertico-suspend requires that recursive minibuffers are enabled by setting the customizable variable enable-recursive-minibuffers to t.
Enables repetition of Vertico sessions via the vertico-repeat, vertico-repeat-previous and vertico-repeat-select commands. If the repeat commands are called from an existing Vertico minibuffer session, only sessions corresponding to the current minibuffer command are offered via completion.
It is necessary to register a minibuffer setup hook, which saves the Vertico state for repetition. In order to save the history across Emacs sessions, enable savehist-mode and add vertico-repeat-history to savehist-additional-variables.
Similar to vertico-indexed-mode, which prefixes candidates with quick keys. Typing these quick keys allows you to select the candidate in front of them. This is designed to be a faster alternative to selecting a candidate with vertico-next and vertico-previous.
Perhaps the most complex extensions, used for fine tuning the Vertico display and other minibuffer modes per command or completion category. For some commands you may want to use the vertico-buffer display and for completion categories like file you prefer the vertico-grid-mode.
This package provides marginalia-mode which adds marginalia to the minibuffer completions. Marginalia are marks or annotations placed at the margin of the page of a book or in this case helpful colorful annotations placed at the margin of the minibuffer for your completion candidates. Marginalia can only add annotations to the completion candidates. It cannot modify the appearance of the candidates themselves, which are shown unaltered as supplied by the original command2.
;; Enable rich annotations using the Marginalia package(use-packagemarginalia;; Bind `marginalia-cycle' locally in the minibuffer. To make the binding;; available in the *Completions* buffer, add it to the;; `completion-list-mode-map'.:bind(:mapminibuffer-local-map("M-A".marginalia-cycle));; The :init section is always executed.:init;; Marginalia must be activated in the :init section of use-package such that;; the mode gets enabled right away. Note that this forces loading the;; package.(marginalia-mode))
This package provides an orderless completion style that divides the pattern into space-separated components, and matches candidates that match all of the components in any order. Each component can match in any one of several ways: literally, as a regexp, as an initialism, in the flex style, or as multiple word prefixes. By default, regexp and literal matches are enabled3.
Consult provides search and navigation commands based on the Emacs completion function completing-read. Completion allows you to quickly select an item from a list of candidates. Consult offers asynchronous and interactive consult-grep and consult-ripgrep commands, and the line-based search command consult-line. Furthermore Consult provides an advanced buffer switching command consult-buffer to switch between buffers, recently opened files, bookmarks and buffer-like candidates from other sources. Some of the Consult commands are enhanced versions of built-in Emacs commands. For example the command consult-imenu presents a flat list of the Imenu with live preview, grouping and narrowing. Please take a look at the full list of commands4.
(use-packageconsult;; Replace bindings. Lazily loaded due by `use-package'.: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)([remapInfo-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):mapisearch-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:mapminibuffer-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;; Optionally configure the register formatting. This improves the register;; preview for `consult-register', `consult-register-load',;; `consult-register-store' and the Emacs built-ins.(setqregister-preview-delay0.5register-preview-function#'consult-register-format);; Optionally tweak the register preview window.;; This adds thin lines, sorting and hides the mode line of the window.(advice-add#'register-preview:override#'consult-register-window);; Use Consult to select xref locations with preview(setqxref-show-xrefs-function#'consult-xrefxref-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-customizeconsult-theme:preview-key'(:debounce0.2any)consult-ripgrepconsult-git-grepconsult-grepconsult-bookmarkconsult-recent-fileconsult-xrefconsult--source-bookmarkconsult--source-file-registerconsult--source-recent-fileconsult--source-project-recent-file;; :preview-key "M-.":preview-key'(:debounce0.4any));; Optionally configure the narrowing key.;; Both < and C-+ work reasonably well.(setqconsult-narrow-key"<");; "C-+";; Optionally make narrowing help available in the minibuffer.;; You may want to use `embark-prefix-help-command' or which-key instead.;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help);; By default `consult-project-function' uses `project-root' from project.el.;; Optionally configure a different project root function.;;;; 1. project.el (the default);; (setq consult-project-function #'consult--default-project--function);;;; 2. vc.el (vc-root-dir);; (setq consult-project-function (lambda (_) (vc-root-dir)));;;; 3. locate-dominating-file;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")));;;; 4. projectile.el (projectile-project-root);; (autoload 'projectile-project-root "projectile");; (setq consult-project-function (lambda (_) (projectile-project-root)));;;; 5. No project support;; (setq consult-project-function nil))
Corfu enhances in-buffer completion with a small completion popup. The current candidates are shown in a popup below or above the point. The candidates can be selected by moving up and down. Corfu is the minimalistic in-buffer completion counterpart of the Vertico minibuffer UI5.
(use-packagecorfu;; Optional customizations;; :custom;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous';; (corfu-auto t) ;; Enable auto completion;; (corfu-separator ?\s) ;; Orderless field separator;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match;; (corfu-preview-current nil) ;; Disable current candidate preview;; (corfu-preselect 'prompt) ;; Preselect the prompt;; (corfu-on-exact-match nil) ;; Configure handling of exact matches;; (corfu-scroll-margin 5) ;; Use scroll margin;; Enable Corfu only for certain modes.;; :hook ((prog-mode . corfu-mode);; (shell-mode . corfu-mode);; (eshell-mode . corfu-mode));; Recommended: Enable Corfu globally. This is recommended since Dabbrev can;; be used globally (M-/). See also the customization variable;; `global-corfu-modes' to exclude certain modes.:init(global-corfu-mode));; A few more useful configurations...(use-packageemacs:init;; TAB cycle if there are only few candidates(setqcompletion-cycle-threshold3);; Emacs 28: Hide commands in M-x which do not apply to the current mode.;; Corfu commands are hidden, since they are not supposed to be used via M-x.;; (setq read-extended-command-predicate;; #'command-completion-default-include-p);; Enable indentation+completion using the TAB key.;; `completion-at-point' is often bound to M-TAB.(setqtab-always-indent'complete));; Use Dabbrev with Corfu!(use-packagedabbrev;; Swap M-/ and C-M-/:bind(("M-/".dabbrev-completion)("C-M-/".dabbrev-expand)):config(add-to-list'dabbrev-ignored-buffer-regexps"\\` ");; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older.(add-to-list'dabbrev-ignored-buffer-modes'doc-view-mode)(add-to-list'dabbrev-ignored-buffer-modes'pdf-view-mode)
By default, when typing, press TAB to start the completion, use C-p or C-n (C-j or C-k can also be used).
(defuncorfu-enable-always-in-minibuffer()"Enable Corfu in the minibuffer if Vertico/Mct are not active."(unless(or(bound-and-true-pmct--active)(bound-and-true-pvertico--input)(eq(current-local-map)read-passwd-map));; (setq-local corfu-auto nil) ;; Enable/disable auto completion(setq-localcorfu-echo-delaynil;; Disable automatic echo and popupcorfu-popupinfo-delaynil)(corfu-mode1)))(add-hook'minibuffer-setup-hook#'corfu-enable-always-in-minibuffer1)
This will enable corfu as long as there’s no other completion active.
Nerd-icons-corfu.el is a library for adding icons to completions in Corfu. It uses nerd-icons.el under the hood and, as such, works on both GUI and terminal6.
Cape provides Completion At Point Extensions which can be used in combination with Corfu, Company or the default completion UI. The completion backends used by completion-at-point are so called completion-at-point-functions (Capfs)7.
;; Add extensions(use-packagecape;; Bind dedicated completion commands;; Alternative prefix keys: C-c p, M-p, M-+, ...:bind(("C-c p p".completion-at-point);; capf("C-c p t".complete-tag);; etags("C-c p d".cape-dabbrev);; or dabbrev-completion("C-c p h".cape-history)("C-c p f".cape-file)("C-c p k".cape-keyword)("C-c p s".cape-elisp-symbol)("C-c p e".cape-elisp-block)("C-c p a".cape-abbrev)("C-c p l".cape-line)("C-c p w".cape-dict)("C-c p :".cape-emoji)("C-c p \\".cape-tex)("C-c p _".cape-tex)("C-c p ^".cape-tex)("C-c p &".cape-sgml)("C-c p r".cape-rfc1345)):init;; Add to the global default value of `completion-at-point-functions' which is;; used by `completion-at-point'. The order of the functions matters, the;; first function returning a result wins. Note that the list of buffer-local;; completion functions takes precedence over the global list.(add-to-list'completion-at-point-functions#'cape-dabbrev)(add-to-list'completion-at-point-functions#'cape-file)(add-to-list'completion-at-point-functions#'cape-elisp-block);;(add-to-list 'completion-at-point-functions #'cape-history);;(add-to-list 'completion-at-point-functions #'cape-keyword);;(add-to-list 'completion-at-point-functions #'cape-tex);;(add-to-list 'completion-at-point-functions #'cape-sgml);;(add-to-list 'completion-at-point-functions #'cape-rfc1345);;(add-to-list 'completion-at-point-functions #'cape-abbrev);;(add-to-list 'completion-at-point-functions #'cape-dict);;(add-to-list 'completion-at-point-functions #'cape-elisp-symbol);;(add-to-list 'completion-at-point-functions #'cape-line))