In a vertico-session type:
9to select the ninth candidate (w/o confirming RET)1 1to select the 11th8 ito insert the 8th candidate into the minibuffer1 2 ato call embark-act on the 12th candidateM-iregular digit behaviour for the completion-session
Example Recordings:
Pay attention to the keys registered in the keycast log buffer on the left. Recordings are made with ambrevar’s gif-screencast.
- Selecting the 12th candidate in a
find-filecompletion. Keys:1 2, note that noRETis pressed for confirmation (the recorded command with no key-event is the timer executing that action).
- Invoking
embark-acton the 12th variable discovered byhelpful-variable. Keys:1 2 a.
vertico-timer is a vertico extension that builds on vertico-indexed and around
the same basic idea of selecting candidates with digit keys. The fastest way to
vertico is usually to narrow the list to one candidate and press RET, however
you need to know enough of a candidate’s name (and be a quick typer). This
package aims to speed up the process for those times that you have to look at
the list.
While vertico-indexed-mode allows you to select candidates by their indices
using prefix arguments, this package makes it even faster by allowing direct
selection with digit keys. So instead of pressing C-u 9 RET to select the ninth
candidate you simply hit 9. Instead of C-u 1 1 RET you type 1 1.
Beware: This introduces a highly opinionated tradeoff. What if you actually
want to input numbers into the minibuffer? While you could always quote-insert
them with C-q, if you actually do find yourself filtering by numbers they
usually come in a bunch, (i.e. filtering denotes).
So the proposed tradeoff by this package is a per-session toggle. This effectively adds a “key-prefix” (the toggle) to the rare case (inputting numbers) and removes it from the common case (selecting candidates). You may find you barely ever need to input numbers into the minibuffer, but this depends on personal usage-patterns.
This package concerns itself with more bells and whistles but really this covers the practical use-case. If you think this functionality can benefit your usage and you want to shave off time from completing candidates, I recommend to jump over to the minimal configuration after installation and get a feel for the basic mechanics before looking at anything fancy.
vertico-timer still uses prefix-arg in the background to allow selecting
multi-digit candidates (hitting 1 2 will select the 12th candidate). It will
pass that baton to vertico-indexed.
After receiving the first digit key a timer starts that executes the default
action on the candidate whose index corresponds to the value of prefix-arg. This
gives you time to append a second digit to prefix-arg.
The timer can be instructed to reset itself with each keypress this is helpful if you define single keys to change the action performed on a target.
- Emacs 29.1 or later
- vertico
- vertico-indexed (included in vertico)
The package is available at https://github.com/ventruvian/vertico-timer.
Add to your packages.el:
(package! vertico-timer :recipe (:host github :repo "ventruvian/vertico-timer"))(use-package vertico-timer
:ensure (:host github :repo "ventruvian/vertico-timer")
:after vertico)(use-package vertico-timer
:straight (:host github :repo "ventruvian/vertico-timer"))Configuring the timer as well as a session toggle is strongly recommended. It is kept rather short (but usable) by default to push you to set one yourself. Everybody has their own sweet spot.
You’ll also want a toggle for number input. Otherwise you’d need to prefix every number
that you want to insert with C-q.
A minimum recommended configuration:
(use-package vertico-timer
;; Seconds to wait before executing the action
:custom (vertico-timer-timeout-seconds 0.25)
;; Actually input numbers into the minibuffer
:bind (:map vertico-map ("M-i" . vertico-timer-toggle-in-session))
:hook (vertico-mode . vertico-timer-mode))A more advanced configuration utilizing changes to the exit action:
(use-package vertico-timer
:custom ; in doom prefer `setq!' over :custom
;; Tell the timer which action you run most often
(vertico-timer-default-action #'vertico-directory-enter)
;; Seconds to wait before executing the action
(vertico-timer-timeout-seconds 0.25)
;; Get extra time for a third key to choose an exit action
(vertico-timer-key-interaction 'reset)
;; Change action hint for default action
(vertico-timer-default-action-hint "exit")
:hook (vertico-mode . vertico-timer-mode)
;; Placeholder bindings, find ones that suit you!
:bind (:map vertico-map
;; "Prefix" to allow for number input
("s-t" . vertico-timer-toggle-in-session)
;; Pre-digit key if you know you'll want to insert into the minibuffer
("s-i" . vertico-timer-prep-insert-action)
;; Probably rarely used. Change back to default action
("s-d" . vertico-timer-prep-default-action)
;; Cycle through registered action pre-digit-press
;; Doing this probably won't make you very fast
("s-<right>" . vertico-timer-cycle-actions-forward)
("s-<left>" . vertico-timer-cycle-actions-backward))
:config
;; Activate the action hint in the minibuffer (in doom prefer `setq!')
(setopt vertico-timer-action-hint-format
vertico-timer-action-hint-default-format)
;; embark-become acts on the input not the candidate so we insert first
(defun i/embark-become ()
(interactive)
(vertico-insert)
(call-interactively #'embark-become))
;; Call embark-act by pressing "a" after digits or "s-a" before
(vertico-timer-register-actions
"a" embark-act :name "act" :prep-key "s-a"
"b" i/embark-become :name "become" :prep-key "s-b"
"SPC" embark-select :name "select" :prep-key "M-SPC" :keep t))Note: The keybindings presented here are not a recommendation, I use totally different ones myself, but since my keyboard layout is differnt from everybody elses there is little sense in sharing mine. These keybindings should be seen as placeholders. If you come up with a set of keybindings that are compatible with regular keyboards and that work well for you please share them and I’ll update this section.
vertico-timer-timeout-seconds: Seconds to wait before executing action (default 0.5)vertico-timer-default-action: Default action function (defaultvertico-exit)vertico-timer-default-action-hint: Hint for default action in overlay (default “default”)vertico-timer-insert-action-hint: Hint for insert action (default “insert”)vertico-timer-key-interaction: How timer interacts with successive digit presses (“reset” or “none”, default “reset”)vertico-timer-action-hint-fstring: Format string for action hint overlay
Enable vertico-timer-mode globally to activate the timer-based selection. It
will automatically enable vertico-indexed-mode (if not already enabled).
Use digit keys to select candidates while completing. Digit keys will highlight the corresponding candidate and start a timer. The action executed by the timer can be changed. If enabled, the current action will be overlayed in the minibuffer.
Available actions during timer:
TAB/i: Insert the candidateRET: Cancel the timer (and execute the default action)- Your own keys registered via
vertico-timer-register-actions
If you need to disable the behavior during a single completion session (e.g., to
input digits as text), bind vertico-timer-toggle-in-session.
For the period the timer runs a high-precedence keymap (a transient map) is activated. The digit keys are bound to it. (Nearly) All other keys are empty.
This keymap vertico-timer-map provides facilties to influence the action the
timer will take on the target with a single letter. For example RET is bound to
it to execute the default action on the candidate right away.
If you want to change the exit-action on a candidate with multi-digit index
(i.e. 11) you may be pressed for time. You can instruct the timer to reset with
every successive digit you press by setting vertico-timer-key-interaction to
'reset.
Use vertico-timer-register-actions with a list of bindings (can be single
letters) and commands to be register them in vertico-timer-map. For example:
(defun i/print-cand ()
(interactive)
(message "hello from %s" (vertico--candidate)))
;; If you want the action hint add :name keys here
(vertico-timer-register-actions
"p" i/print-cand
"a" embark-act)With this snippet you will have two extra actions available after selection.
When you press 3 p a greeting will appear from the 3rd candidate and if you
press 3 a you will invoke embark-act on it. One is probably more useful than the
other.
Here is a little comparison of keypresses between this configuration of
vertico-timer and a setup with embark’s quick-start settings:
| Use Case | vertico-indexed | vertico-timer |
|---|---|---|
| Select 5th candidate | C-u 5 RET | 5 |
| Select 10th candidate | C-u 1 0 RET | 1 0 |
| Insert 7th candidate | C-u 7 TAB | 7 i |
7 TAB | ||
embark-act on 6th | C-u 6 C-. | 6 a |
embark-become on 11th | C-u 1 1 TAB C-. B | 1 1 b |
Okay that last one was a bit contrieved as you could use the same exit action
(combining vertico-insert with embark-become) in vertico-indexed, but you’d need
another unweildly keychord for it.
You can activate an overlay in the minibuffer that displays your current choice
of action by setting vertico-timer-action-hint-format to a valid (possibly
propertized) string. %s will be replaced by the name of your action in the
minibuffer. The default will get you started:
(setopt vertico-timer-action-hint-format
vertico-timer-action-hint-default-format)Using setopt (or setq! in doomland) will validate the string first, if you use
setq you have to ensure that your string contains exactly one %s as the format
parameter.
The name shown is the value of the :name key in vertico-timer-register-actions.
So in the example from earlier add:
(defun i/print-cand ()
(interactive)
(message "hello from %s" (vertico--candidate)))
(vertico-timer-register-actions
"p" i/print-cand :name "greet"
"a" embark-act :name "act")If you leave out the :name key a generated name like cust-g408 will be shown for
each of your anonymous actions. This is probably not very helpful so if you use the action
hint set a name as well.
You can also prepare an action if you know you want to change it but haven’t
found the candidate yet, effectively inverting the mental model. An
“insert-action” (calling vertico-insert) and a “default-action” are
preconfigured, bind vertico-timer-prep-insert-action and
vertico-timer-prep-default-action in vertico-map if you want to be able to set
these before you start the timer.
Your custom actions can be prepared by passing a :prep-key argument to
vertico-timer-register-actions:
(keymap-set vertico-map "s-i" #'vertico-timer-prep-insert-action)
(vertico-timer-register-actions
"a" embark-act :name "act" :prep-key "s-a")Now you will be able to hit s-i 3 to insert the 3rd candidate into the
minibuffer with leasure or s-a 3 to embark-act on it (again these keybindings are
completely made up and not battle-tested).
NOTE: vertico-quick is probably the more prudent choice for this workflow, since it’s letter overlays are always easily in reach. A slight counterpoint could be that they only appear after hitting the keybinding. In the future I may provide an option to switch to vertico-quick with prep-keys.
You may define an action that doesn’t exit the minibuffer (say embark-select).
By default vertico-timer reset’s the action back to default each time it runs
it. However you may want to run that same operation again.
For example if you are in a consult-yank-pop session and you want to
embark-select a couple of candidates for bulk insertion with embark-act-all then
it is bothersome to have to hit SPC after each digit again or prep the action in
between digit keypresses. Instead you can define the action to stay active by
passing a :keep keyword argument to vertico-timer-register-actions. If any such
action is switched to it will stick around as long as the minibuffer is active.
(vertico-timer-register-actions
"SPC" embark-select :keep t)So in the yank-pop example you would hit: M-y 3 SPC 4 5 6 to mark 4 candidates and yank
them all into the buffer with embark-act-all.
This goes particularly well with a prep-key, with the below configuration you
can M-y M-SPC 3 4 5 6 to achieve the same result.
(vertico-timer-register-actions
"SPC" embark-select :prep-key "M-SPC" :keep t)Two functions are available to cycle all available exit actions:
vertico-timer-cycle-actions-forwardvertico-timer-cycle-actions-backward
If you want you can bind them, but cycling through things never encourages speed, but they may aid in discovery of the functionality. If you invoke a cycle command the action hint will display for the session regardless of the global setting.
Summarizing, some possible workflows come to mind, let’s name them for pizzazz:
- Versatile
- Set a long timer (>0.5s). Prefer exit actions over waiting for
timeout. Use default action on
RET, but have custom actions on easy keys for versatility. - Speed
- Short timer (~0.25s) and unset timer-reset. Use default action mostly, let timer confirm selection automatically. Requires fast typing, and the timer saves a keypress.
- Compromise
- Short timer (
0.25s), but with ~vertico-timer-key-interactionset toreset, allowing the second digit to reset the timer to be able to choose an exit action. - Goofy
- Press a
:prep-keyfirst to select an action, then digits to select candidate. Maybe useful when you know the action but not the candidate yet, e.g.,embark-becomebefore finding the target command. Compatible with1.-~3.~
vertico-timer-mode: Global minor mode to enable/disablevertico-timer-toggle-in-session: Toggle mode for current sessionvertico-timer-cycle-actions-forward: Cycle to next registered actionvertico-timer-cycle-actions-backward: Cycle to previous registered actionvertico-timer-prep-default-action: Prepare default actionvertico-timer-prep-insert-action: Prepare insert action- Generate your own commands with
vertico-timer-register-actions
Two keymaps are relevant for this package:
- vertico-map
- For all commands that prepare an action as well as for the session-toggle.
This package doesn’t bind to
vertico-mapon it’s own but you are adviced to bind some keys there to be able to use this package effectively. The:prep-keybinding passed tovertico-timer-register-actionswill end up in this map. - vertico-timer-map
- All command active during the timer-duration.
Default actions are bound to
RETandTAB/i, the digit keys are populate for base functionality and the bindings ofvertico-timer-register-actionsend up here.
During the timer:
- Digit keys: Select candidate and interact with timer
TAB/i: Switch to insert actionRET: Confirm default action- Custom keys as registered
In vertico-map:
- digit keys: Adapted for timer selection
s-t: Toggle in session (example)- Prep keys for advance action selection (examples
s-a, etc.) - Cycling keys (examples
s-<right>, etc.)
- Take some time to consider the keys you bind. The value of this package drastically depends on how comfortably you can type keys in succesion.
- If your keyboard (-layout) allows accessing digit keys with one hand (i.e. if you have a number block) consider binding custom actions to keys accessible with the other hand.
Contributions welcome! Feel free to check the issues page or submit a pull requests or edit the wiki to share your custom actions.
This package is licensed under GPLv3. See LICENCE for details.

