Emacs Completions¶
No Emacs configuration is complete without a lengthy discussion on how completions are handled.
*Completions*¶
I actually quite like the default *Completions* buffer and used it extensively from Emacs 29.1 to around 30.1.
(Also seeing how there is a bunch of stuff coming in Emacs 31 I’m sure I will switch back again to it before long! 😅)
My config wasn’t anything particuarly exciting, as I only:
Tweaked some options that control how it is rendered
emacsinit.el(setq completions-detailed t completions-format 'one-column completions-group t completions-header-format (propertize "%s candidates\n" 'face 'shadow) completions-max-height 15 completion-show-help nil)
Tweaked some options that control its behaviour
emacsinit.el(setq completion-auto-help 'visible completion-auto-select 'second-tab completion-cycle-threshold 3)
That is to say, the
*Completions*buffer only opens on the second attempt at completing something. However, once it is open keep it updated and only focus it on the second completion attempt with no progress made.If there are only 3 or fewer options, don’t bother with the
*Completions*buffer at all.Finally, use C-n and C-p to cycle through completion candidates.
(dolist (kmap (list minibuffer-local-map completion-in-region-mode-map)) (keymap-set kmap "C-p" #'minibuffer-previous-completion) (keymap-set kmap "C-n" #'minibuffer-next-completion))
However there are occasions where you want just a little bit… more.
Consult¶
Consult, the grab-bag of utility functions built on top of completing-read.
I admit, I probably don’t use this as much as I should.
emacs
init.el
(use-package consult
:ensure t
:custom
(consult-preview-key "M-.")
(consult-narrow-key "<")
(enable-recursive-minibuffers t)
:bind (("C-x b" . consult-buffer)
("C-c n" . consult-minor-mode-menu)
;; Search for...
("M-s l" . consult-line)
;; Goto ...
("M-g m" . consult-mark)
("M-g M" . consult-global-mark)))
Notes:
I don’t often want the live preview feature, but it’s nice to be able to opt into it by hitting M-.
consult-narrow-keyis cool, where a command has multiple groups e.g.consult-bufferhitting something like < p filters the list down to project buffers. Yes, you can do the same with p SPC but sinceconsult-narrow-keytriggers a keymap you can hit C-h to see all the available groups and their associated keys.Coupled with
embark-prefix-help-commandbelow, you get an interactive, searchable list! (Only if you set ‘enable-recursive-minibuffers’ to ‘t’)consult-minor-mode-menuis very nice, gives you an interactive view to manage all of your minor modes! With it, I see no need to display them all in the modeline anymore.
Embark¶
See also
Embark, another excellent package, that I should try and use more deeply!
emacs
init.el
(use-package embark
:ensure t
:bind (("C-." . embark-act) ;; C-u C-. to have embark-act stay open after taking an aciton.
("M-." . embark-dwim)
("C-h b" . embark-bindings))
:config
(setq prefix-help-command #'embark-prefix-help-command)
(setq embark-indicators
'(embark-minimal-indicator
embark-highlight-indicator
embark-isearch-highlight-indicator)))
Since I have consult installed, use the recommended emabrk-consult package (though I admit I’m not sure what it does!)
emacs
init.el
(use-package embark-consult
:after (embark consult)
:ensure t)
To get the most out of Embark, you should also install marginalia as it improves the completion metadata provided by many built-in commands, allowing Embark to offer better suggestions.
emacs
init.el
(use-package marginalia
:ensure t
:config
(marginalia-mode))
Orderless¶
Continuing with the established theme I use the orderless completion style as even a basic config is useful, but it would be great to experiment with some style dispatchers!
emacs
init.el
(use-package orderless
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles basic partial-completion)))))
Vertico¶
See also
- VOMPECCC: A Modular Completion Framework for Emacs
The article that pushed me over the edge to actually setting vertico up.
As mentioned in the *Completions* section above, I was really happy with the built-in completions experience. I find the ~95% of the time, I already know what I’m trying to select and I’m only really looking for a bit of tab-completion to save on the typing.
Therefore vertico’s unobtrusive mode is perfect.
To cover that remaining 5%, I can use the multiform extension to switch to a different mode for some pre-determined cases, or on an ad-hoc basis thanks to the vertico-mutliform-map keymap.
So I have arrived at the following config.
emacs
init.el
(use-package vertico
:ensure t
:init
(vertico-mode)
:config
(setq vertico-multiform-commands
'((consult-line buffer)
(consult-imenu buffer)
(consult-minor-mode-menu buffer)))
(setq vertico-multiform-categories
'((embark-keybinding grid)
(t unobtrusive)))
(vertico-multiform-mode t))
The trick was realising I could use (t unobtrusive) as a fallback to active the unobtrusive mode by default!
As for completion-in-region, I still don’t feel the need for something like corfu but I was definitely excited to see the following snippet in vertico’s README.
emacs
init.el
(setq completion-in-region-function #'consult-completion-in-region)
So I get to keep my consistent completion experience regardless of what I am completing!