What a year this 2020. Beside the pandemic changing our lives in unpredictable
ways, from the perspective of my Emacs usage much was going on in my
until I felt that a temporary break was necessary.
Most of my tinkering concerned the minibuffer and its completion mechanisms. I finished last year and started this one with Helm, but I am about to close 2020 with the built-in minibuffer completion and Embark providing candidates. A solution that Protesilaos Stavrou explored and which has been really suiting me.
Before detailing how I adapted his approach to my preferences, though, let me give you a bit of rationale. First, Helm rocks and it rocks hard. Its power is evident after a couple of hours with it. I briefly used Icomplete tweaked to display its results vertically, but I didn’t find it responsive enough to stick with it. Then I found out about Selectrum, which fixed the responsiveness but eventually was not adding a significant difference compared to Helm. True, Selectrum has a simpler codebase, but were I only to look at my daily interactions with Emacs, only the user interface can tell Helm and Selectrum apart.
Protesilaos took a different path. He wants to understand the code in front of him, so the less changes the better. In this regard Helm, Selectrum, and even Icomplete add a layer of indirection between him and the minibuffer. He is right in this. The minibuffer is more capable than the plethora of completion frameworks may suggest, and one can leverage its strength without forcing it to behave in a totally new way. Protesilaos’ reasoning got me thinking. Once again, am I looking for a solution from the outside before having really understood what lies underneath my beloved text editor?
Following Protesilaos’ steps, I set up the minibuffer to rely only on orderless
and Embark, with Consult chiming in for a some of operations like better history
shell-mode and an improved
apropos. What I added to Protesilaos’ code is the
only thing that I felt was missing: a command to search for the symbol at point
in my project, with the results displayed in an
embark-live-occur window in
order to quickly jump to a specific entry. Over at the Consult’s GitHub there
are talks about a
consult-rg utility which would serves this purpose, and there
has been suggestions of using
project-find-regexp as well.
(defun mu-project-find-refs () "Use `project-find-regexp' to search for thing at point." (interactive) (if-let (tap (thing-at-point 'symbol)) (project-find-regexp tap) (message "Nothing at point to search for")))
Easy enough to understand. However, if you, like me, set up Embark like
Protesilaos does you’ll notice that this command doesn’t show any candidate
unless you type something at the
Jump to definition prompt. The candidates are
there already, though, so I have to avoid waiting for an input and display the
candidate list immediately.
The solution is straightforward: just remove
minibuffer-setup-hook and use
embark-live-occur-after-delay instead. I added a
:before advice on
mu-project-find-refs for this. The beauty of this advice is
that it works elsewhere as well. For instance, I have been using it for
Note that this advice requires a little change to the original
minibuffer-setup-hook I have lifted from Protesilaos. Instead of adding
embark-live-occur-after-input to it I am using this to ensure only
embark-live-occur-after-input is present.
(defun mu-embark-live-occur-after-input () "Ensure only `embark-live-occur-after-input' is active." (remove-hook 'minibuffer-setup-hook #'embark-live-occur-after-delay) (add-hook 'minibuffer-setup-hook #'embark-live-occur-after-input))
Without a dedicated completion framework the minibuffer may feel rather basic at
first, but do not let it deceive you with its frugality. Like
project.el, all it
needs is love.