Vertico provides a performant and minimalistic vertical completion UI based on
the default completion system. The main 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 flexible and extensible. Additional enhancements
are available as extensions or complementary packages. The code base is small
and maintainable (vertico.el
is only about 600 lines of code without white
space and comments).
- Vertical display with arrow key navigation
- Prompt shows the current candidate index and the total number of candidates
- The current candidate is inserted with
TAB
and selected withRET
- Non-existing candidates can be entered by moving the point to the prompt line
- Configurable sorting by history position, length and alphabetically
- Long candidates with newlines are formatted to take up less space
- Deferred completion style highlighting for performance
- Support for annotations (
annotation-function
andaffixation-function
) - Support for grouping and group cycling commands (
group-function
)
Vertico defines its own local keymap in the minibuffer which is derived from
minibuffer-local-map
. The keymap keeps most of the fundamental-mode
keybindings intact and remaps and binds only a handful of commands. Note in
particular the binding of TAB
to vertico-insert
and the bindings of
vertico-exit/exit-input
.
beginning-of-buffer
,minibuffer-beginning-of-buffer
->vertico-first
end-of-buffer
->vertico-last
scroll-down-command
->vertico-scroll-down
scroll-up-command
->vertico-scroll-up
next-line
,next-line-or-history-element
->vertico-next
previous-line
,previous-line-or-history-element
->vertico-previous
forward-paragraph
->vertico-next-group
backward-paragraph
->vertico-previous-group
exit-minibuffer
->vertico-exit
kill-ring-save
->vertico-save
C-<return>
->vertico-exit-input
TAB
->vertico-insert
Vertico is available from GNU ELPA. You can install it directly via
package-install
. After installation, you can activate the global minor mode
with M-x vertico-mode
. In order to configure Vertico and other packages in
your init.el, you may want to take advantage of use-package
. I recommend to
give Orderless completion a try, which is different from the prefix TAB
completion used by the basic default completion system or in shells. Here is
an example configuration:
;; Enable vertico
(use-package vertico
: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)
)
;; Optionally use the `orderless' completion style. See
;; `+orderless-dispatch' in the Consult wiki for an advanced Orderless style
;; dispatcher. Additionally enable `partial-completion' for file path
;; expansion. `partial-completion' is important for wildcard support.
;; Multiple files can be opened at once with `find-file' if you enter a
;; wildcard. You may also give the `initials' completion style a try.
(use-package orderless
:init
;; Configure a custom style dispatcher (see the Consult wiki)
;; (setq orderless-style-dispatchers '(+orderless-dispatch)
;; orderless-component-separator #'orderless-escapable-split-on-space)
(setq completion-styles '(orderless)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; Alternatively try `consult-completing-read-multiple'.
(defun crm-indicator (args)
(cons (concat "[CRM] " (car args)) (cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-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.
;; (setq read-extended-command-predicate
;; #'command-completion-default-include-p)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t))
See also the Vertico Wiki for additional configuration tips.
The bindings of the minibuffer-local-completion-map
are not available in
Vertico by default. This means that TAB works differently from what you may
expect from the default Emacs completion system.
If you prefer to have the default completion commands a key press away you can
add new bindings or even replace the Vertico bindings. Then the default
completion commands behave as usual. For example you can use M-TAB
to cycle
between candidates if you have set completion-cycle-threshold
.
(define-key vertico-map "?" #'minibuffer-completion-help)
(define-key vertico-map (kbd "M-RET") #'minibuffer-force-complete-and-exit)
(define-key vertico-map (kbd "M-TAB") #'minibuffer-complete)
The orderless
completion style does not support completion of a common prefix
substring, as you may be familiar with from shells or the basic default
completion system. The reason is that the Orderless input string is usually
not a prefix. In order to support completing prefixes you may want to combine
orderless
with substring
in your completion-styles
configuration.
(setq completion-styles '(substring orderless))
Alternatively you can experiment with the built-in completion-styles, e.g.,
adding partial-completion
or flex
. The partial-completion
style is important
to add if you want to open multiple files at once with find-file
using
wildcards. In order to open multiple files at once, you have to move to the
prompt and then press RET
.
(setq completion-styles '(basic substring partial-completion flex))
Because Vertico is fully compatible with Emacs default completion
system, further customization of completion behavior can be achieved
by setting the designated Emacs variables. For example, one may wish
to disable case-sensitivity for file and buffer matching when built-in
completion styles are used instead of orderless
:
(setq read-file-name-completion-ignore-case t
read-buffer-completion-ignore-case t
completion-ignore-case t)
The completion-at-point
command is usually bound to M-TAB
or TAB
. In case you
want to use Vertico for completion-at-point/completion-in-region, you can use
the function consult-completion-in-region
provided by the Consult package.
;; Use `consult-completion-in-region' if Vertico is enabled.
;; Otherwise use the default `completion--in-region' function.
(setq completion-in-region-function
(lambda (&rest args)
(apply (if vertico-mode
#'consult-completion-in-region
#'completion--in-region)
args)))
The completion-in-region-function
setting also affects TAB completion in the
minibuffer when M-:
(eval-expression
) is used.
You may also want to look into my Corfu package, which provides a minimal
completion system for completion-in-region
in a child frame popup. Corfu is
also a narrowly focused package and developed in the same spirit as Vertico.
Consult offers an enhanced completing-read-multiple
implementation which you
can use with Vertico.
(advice-add #'completing-read-multiple
:override #'consult-completing-read-multiple)
We maintain small extension packages to Vertico in this repository in the
subdirectory extensions/. The extensions are installed together with Vertico
if you pull the package from ELPA. The extensions are of course inactive by
default and can be enabled manually if desired. Furthermore it is possible to
install all of the files separately, both vertico.el
and the vertico-*.el
extensions. Currently the following extensions come with the Vertico ELPA
package:
- vertico-buffer:
vertico-buffer-mode
to display Vertico in a separate buffer - vertico-directory: Commands for Ido-like directory navigation
- vertico-flat:
vertico-flat-mode
to enable a flat, horizontal display - vertico-grid:
vertico-grid-mode
to enable a grid display - vertico-indexed:
vertico-indexed-mode
to select indexed candidates with prefix arguments - vertico-mouse:
vertico-mouse-mode
to support for scrolling and candidate selection - vertico-quick: Commands to select using Avy-style quick keys
- vertico-repeat: The command
vertico-repeat
repeats the last completion session - vertico-reverse:
vertico-reverse-mode
to reverse the display
With these extensions it is possible to adapt Vertico such that it matches
your preference or behaves similar to other familiar UIs. For example, the
combination vertico-flat
plus vertico-directory
resembles Ido in look and
feel. For an interface similar to Helm, the extension vertico-buffer
allows
you to configure more freely where the completion buffer opens, instead of
growing the minibuffer.
Configuration example for vertico-directory
:
;; Configure directory extension.
(use-package vertico-directory
:ensure nil
;; More convenient directory navigation commands
:bind (:map vertico-map
("RET" . vertico-directory-enter)
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word))
;; Tidy shadowed file names
:hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
Vertico integrates well with complementary packages, which enrich the completion UI. These packages are fully supported:
- Marginalia: Rich annotations in the minibuffer
- Consult: Useful search and navigation commands
- Embark: Minibuffer actions and context menu
- Orderless: Advanced completion style
In order to get accustomed with the package ecosystem, I recommed the following approach:
- Start with plain Emacs.
- Install and enable Vertico to get incremental minibuffer completion.
- Install Orderless and/or configure the built-in completion styles for more flexible minibuffer filtering.
- Install Marginalia if you like rich minibuffer annotations.
- Install Embark and add two keybindings for
embark-dwim
andembark-act
. I am usingM-.
andC-.
. These commands allow you to act on the object at point or in the minibuffer. - Install Consult if you want additional featureful completion commands,
e.g, the buffer switcher
consult-buffer
with preview or the line-based searchconsult-line
. - Install Embark-Consult and Wgrep for export from
consult-line
tooccur-mode
buffers and fromconsult-grep
to editablegrep-mode
buffers.
You don’t have to use all of these components. Use only the ones you like and
the ones which fit well into your setup. The steps 1. to 4. introduce no new
commands over plain Emacs. Step 5. introduces the new commands embark-act
and
embark-dwim
. In step 6. you get the Consult commands, some offer new
functionality not present in Emacs already (e.g., consult-line
) and some are
substitutes (e.g., consult-buffer
for switch-to-buffer
).
An often requested feature is the ability to display the completions in a child frame popup. I do not recommend this, since from my experience it introduces more problems than it solves. Child frames can feel slow and sometimes flicker. On the other hand the completion display appears right in your focus at the center of the screen, leading to a modern look and feel. Please give these packages a try and judge for yourself.
- mini-frame: Display the entire minibuffer in a child frame.
- mini-popup: Slightly simpler alternative to mini-frame.
- vertico-posframe: Display only the Vertico minibuffer in a child frame using the posframe library.
There are many alternative completion UIs, each UI with its own advantages and disadvantages.
Vertico aims to be 100% compliant with all Emacs commands and achieves that
with a minimal code base, relying purely on completing-read
while avoiding to
invent its own APIs. Inventing a custom API as Helm or Ivy is explicitly
avoided in order to increase flexibility and package reuse. Due to its small
code base and reuse of the Emacs built-in facilities, bugs and compatibility
issues are less likely to occur in comparison to completion UIs or full
completion systems, which reimplement a lot of functionality.
Since Vertico only provides the UI, you may want to combine it with some of the complementary packages, to give a full-featured completion experience similar to Helm or Ivy. Overall the packages in the spirit of Vertico have a different style than Helm or Ivy. The idea is to have smaller independent components, which one can add and understand step by step. Each component focuses on its niche and tries to be as non-intrusive as possible. Vertico targets users interested in crafting their Emacs precisely to their liking - completion plays an integral part in how the users interacts with Emacs.
There are other interactive completion UIs, which follow a similar philosophy:
- Selectrum: Selectrum has a similar UI as Vertico, since it directly inspired Vertico. The Selectrum code base is more complex. Unfortunately Selectrum is not fully compatible with every Emacs completion command (Issue #481), since it uses its own filtering infrastructure, which deviates from the standard Emacs completion facilities. Vertico additionally has the ability to cycle over candidates, offers commands for grouping support and comes with a rich set of extensions.
- Icomplete-vertical: This package enhances the Emacs builtin Icomplete with a
vertical display. In contrast to Vertico, Icomplete rotates the candidates
such that the current candidate always appears at the top. From my
perspective, candidate rotation feels a bit less intuitive than the UI of
Vertico or Selectrum. Note that Emacs 28 offers a built-in
icomplete-vertical-mode
. - Mct: Minibuffer and Completions in Tandem. Mct reuses the default
*Completions*
buffer and enhances it with automatic updates and additional keybindings, to select a candidate and move between minibuffer and completions buffer. Mct is great if you prefer an unobtrusive UI since it can be configured to open only when requested. Furthermore since Mct uses a fully functional buffer you can reuse all your familar buffer commands inside the completions buffer. The main distinction to an approach like Vertico’s is that*Completions*
buffer displays all matching candidates. On the one hand this is good since it allows you to interact with all the candidates and jump around with Isearch or Avy. On the other hand it necessarily causes a small slowdown in comparison to Vertico, which only displays a small subset of candidates.
Vertico is robust in most scenarios. However some completion commands make certain assumptions about the completion styles and the completion UI. Some of these assumptions may not hold in Vertico or other UIs and require minor workarounds.
org-refile
uses org-olpath-completing-read
to complete the outline path
in steps, when org-refile-use-outline-path
is non-nil.
Unfortunately the implementation of this Org completion table assumes that the default completion UI is used. In order to fix the issue at the root, the completion table should make use of completion boundaries similar to the built-in file completion table.
In order to workaround the issues with the current implementation I recommend to disable the outline path completion in steps. The completion on the full path is also faster since the input string matches directly against the full path, which is particularily useful with Orderless.
(setq org-refile-use-outline-path 'file
org-outline-path-complete-in-steps nil)
The text menu bar works well with Vertico but always shows a *Completions*
buffer, which is unwanted if you use the Vertico UI. This completion buffer
can be disabled as follows.
(advice-add #'tmm-add-prompt :after #'minibuffer-hide-completions)
The command ffap-menu
shows the ==*Completions*= buffer by default like
tmm-menubar
, which is unnecessary with Vertico. This completion buffer can be
disabled as follows.
(advice-add #'ffap-menu-ask :around (lambda (&rest args)
(cl-letf (((symbol-function #'minibuffer-completion-help)
#'ignore))
(apply args))))
In combination with Orderless, hostnames are not made available for
completion after entering /ssh:
. In order to avoid this problem, the basic
completion style should be specified for the file completion category.
(setq completion-styles '(orderless)
completion-category-overrides '((file (styles basic partial-completion))))
For users who are familiar with the completion-style
machinery: You may also
define a custom completion style which sets in only for remote files!
(defun basic-remote-try-completion (string table pred point)
(and (vertico--remote-p string)
(completion-basic-try-completion string table pred point)))
(defun basic-remote-all-completions (string table pred point)
(and (vertico--remote-p string)
(completion-basic-all-completions string table pred point)))
(add-to-list
'completion-styles-alist
'(basic-remote basic-remote-try-completion basic-remote-all-completions nil))
(setq completion-styles '(orderless)
completion-category-overrides '((file (styles basic-remote partial-completion))))
Since this package is part of GNU ELPA contributions require a copyright assignment to the FSF.