2023-02-22 Candidate selection in Emacs TRIGGER WARNING: Strong opinions and a lot of sarcasm ahead. Introductory thoughts ~~~~~~~~~~~~~~~~~~~~~ Candidate selection/completion in Emacs is a hot topic[1] where you can chose from a multitude of different packages and configurations options. In the ancient times there was only helm[2]. A feature-rich, bloated and laggy "incremental completion and selection narrowing framework" with an intimidating amount of functionality and documentation. After helm came Ivy[3]: a supposedly lightweight alternative to helm which suffered from not-invented-here syndrome so it basically became just another helm. The newest kid on the block is vertico[4]. But unlike the others vertico is only a tool for candidate selection but offers not much else. To get the same functionality as for example helm, one has to throw several other modularized packages like orderless, marginalia, embark, etc in the mix so you can franken-stitch together a candidate selection framework of your own liking. So now instead of one big package you have to take care of five smaller ones. Of course tinkering with Emacs is fun but it is also really time consuming. Needless to say I tried all of the aforementioned packages but I always struggle using any them for longer periods of time. It does not take long for me to encounter some minor or even major annoyances with these frameworks. I also found that in my workflow flex-matching is really annoying and unhelpful. In the end I keep going back to vanilla Emacs with some customized settings. Instead of tweaking every little aspect of how I want (or rather how I think I want) Emacs to behave, which is really a challenging, even mind-bending task, I instead try to stick to defaults as much as possible. Doing so some things seem to be a bit awkward at first but the power of muscle memory does mitigate this in the long run. Configuration ~~~~~~~~~~~~~ What I have done here is mimicking the behaviour of the bash shell[5]. The up-arrow key searches backwards through the minibuffer history for the already typed in string. For example on my system if I type M-x i n pressing the up-arrow key completes the command `indent-region` from my minibuffer history. If I'm looking for something different I press UP again. If I want a list of all possible completions I just press TAB. With M-v I can easily jump into the completion window to select a candidate. Here is the whole config: ;; really important, saves minibuffer history between sessions (savehist-mode 1) ;; delete duplicates from history (setq history-delete-duplicates t) ;; ignore case in the minibuffer (setq read-buffer-completion-ignore-case t) (setq read-file-name-completion-ignore-case t) (setq completion-ignore-case t) ;; this is the real meat, type the first few letters of a ;; command/filename and then use the history elements to ;; complete it with UP/DOWN (define-key minibuffer-local-map (kbd "<up>") 'previous-complete-history-element) (define-key minibuffer-local-map (kbd "<down>") 'next-complete-history-element) ;; if there are only three completions candidates left cycle ;; though them with TAB (setq completion-cycle-threshold 3) ;; alternative keybinding for `switch-to-completions` (define-key minibuffer-local-map (kbd "M-SPC") 'switch-to-completions) Conclusion ~~~~~~~~~~ Naturally this is the only sensible way of doing candidate selection in Emacs. Everything else would just be stupid *wink* *wink*. Footnotes ~~~~~~~~~ [1] https://old.reddit.com/r/emacs/comments/117zdnu/what_are_the_benefits_of_vertico_over_helm_or_ivy/ [2] https://emacs-helm.github.io/helm/ [3] https://github.com/abo-abo/swiper [4] https://github.com/minad/vertico [5] With these setting in the .bashrc: bind '"\e[A": history-search-backward' bind '"\e[B": history-search-forward'