emacs/var/elfeed/db/data/ad/ad7d58657ef43f2e02764dd622669b6eb03120b5
2022-01-03 12:49:32 -06:00

90 lines
7.5 KiB
Plaintext

<p>My Emacs tweaking tends to go in waves. I keep an eye on the <a href="https://reddit.com/r/emacs">Emacs subreddit</a> and
the Doom Discord channel on a fairly regular basis, but I try not to jump on
every cool new package I see discussed there. Every now and again though, I see
something interesting which coincides with an itch to tinker with Emacs, and
away I go&hellip; This time, it was reading discussions about a constellation of
relatively new packages concerned with incrementally narrowing lists (and other
related functions) that caught my eye. This sounds very niche, but for many
people (me included) being presented with a list of things and being able to
type to incrementally narrow the list and then select something is a core part
of the Emacs UI. Since I use Doom, and it offers you an easy way to choose
either <a href="https://github.com/abo-abo/swiper">Ivy</a> or <a href="https://github.com/emacs-helm/helm">Helm</a>, I had been using Ivy, for the sake of easy configuration.
Both are fine packages, but having tried both, I preferred Ivy&rsquo;s more minimal
interface, and the fact that it used the minibuffer rather than a buffer for
completions. However, it &mdash; and the related packages, Counsel and Swiper &mdash;
are somewhat complex and difficult to get to grips with. I was also not using
all the features that they provided, so was curious if I would enjoy using
something even simpler. That&rsquo;s why I tried out <a href="https://github.com/raxod502/selectrum#why-use-selectrum">Selectrum</a>.</p>
<p>The Selectrum README page on GitHub gives an admirably thorough and clear
explanation about the niche that it is trying to fill, and how it compares to
other similar packages. What I like about it is that it tries to stick as
closely as possible to using Emacs&rsquo; standard APIs, so that once you enable it,
many standard Emacs commands (like <code>find-file</code>) automatically use Selectrum. It
also doesn&rsquo;t try to do everything, so it really <em>only</em> provides incremental
narrowing, leaving sorting and filtering (and actions to operate on the selected
candidate) to other packages. This means that you have a bit more package
installation and configuration to do up front, but it also means that you can
pick and choose which elements you need and leave the others, so you end up with
a simpler system. I chose to use the following additional packages:</p>
<h3 id="prescient-dot-el">Prescient.el</h3>
<p><a href="https://github.com/raxod502/prescient.el">prescient.el</a> sorts choices in a more intelligent way, remembering your recent
selections and bubbling those to the top of the list. It also enables you to
toggle on and off different ways of matching a candidate (for example by the
initial letter of each word, or by regular expression). I have found <code>prescient</code>
to work very well in practice. It also works with Ivy and Helm and other
incremental narrowing packages, so you can use it even if you don&rsquo;t use
Selectrum.</p>
<h3 id="consult">Consult</h3>
<p><a href="https://github.com/minad/consult">consult</a> works with any function that works with Emacs&rsquo; built-in <code>completing-read</code>
function (including Selectrum). It is intended as a rough replacement for
<code>counsel</code>, and provides some useful functions for searching a buffer interactively
for text, searching headlines (in Org or Markdown files, or any mode that
implements <code>outline-mode</code>). It has a very handy function <code>consult-buffer</code>. Despite
the name, it is a multi-purpose function which enables you to search and select
among a list of buffers, files and bookmarks by default, so you don&rsquo;t need
separate commands to search each of those categories. If you do want to filter
the list because you know you are searching for a buffer, not a file, for
example, you can prefix your search with &lsquo;b&rsquo; (or &lsquo;f&rsquo; for file, or &rsquo;m&rsquo; for
bookmark). I&rsquo;ve found this so handy that I have bound it to Doom&rsquo;s <kbd>SPC SPC</kbd>
binding for easy access. I previously often found myself searching for a buffer
first, before realising that I needed to search for a file as the buffer
containing that file wasn&rsquo;t yet open. This stops me having to think about the
distinction, but allows me to narrow the list if I am sure.</p>
<h3 id="marginalia">Marginalia</h3>
<p><a href="https://github.com/minad/marginalia/">marginalia</a> adds &lsquo;annotations&rsquo; to some of the lists presented by Selectrum. For
example, if you use <kbd>M-x</kbd> it can add key-bindings and also docstrings to the list
of commands. Ivy did this too, and I found it extremely useful.</p>
<h3 id="embark">Embark</h3>
<p><a href="https://github.com/oantolin/embark/">embark</a> is the package I am least sure about whether I will keep, but it is
handy. It enables you to hit a key-binding when you have a candidate selected in
a list and apply some action to the item. It knows whether the item is a file or
buffer or some other item, so it presents a list of appropriate actions for
each, like opening a buffer in the other window, or renaming a file. There are
of course many other ways to achieve this in Emacs, but I find that the method
of selecting something first, then choosing how to act on it works well for me.
It is also really simple to add new actions, and I added one to jump to the
dired buffer for a file. That was as simple as the snippet below in my <kbd>config.el</kbd>
file (swap <code>use-package!</code> for <code>use-package</code> if you are not using Doom):</p>
<div class="highlight"><pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(<span style="color:#369">use-package!</span> <span style="color:#369">embark</span>
<span style="color:#038">:after</span> <span style="color:#369">selectrum</span>
<span style="color:#038">:bind</span> (<span style="color:#038">:map</span> <span style="color:#369">minibuffer-local-map</span>
(<span style="color:#d20;background-color:#fff0f0">&#34;C-o&#34;</span> . <span style="color:#369">embark-act</span>)
(<span style="color:#d20;background-color:#fff0f0">&#34;C-S-o&#34;</span> . <span style="color:#369">embark-act-noexit</span>)
<span style="color:#038">:map</span> <span style="color:#369">embark-file-map</span>
(<span style="color:#d20;background-color:#fff0f0">&#34;j&#34;</span> . <span style="color:#369">dired-jump</span>)))
</code></pre></div><h3 id="is-it-better-than-ivy-counsel-swiper">Is it better than Ivy/Counsel/Swiper?</h3>
<p>This setup doesn&rsquo;t do anything that that Ivy and friends didn&rsquo;t. It does some
things a bit differently, and in ways I prefer. The <code>consult-outline</code> command
presents Org headings in a way I find much easier to navigate, for example.
I am going to stick with these packages because I find the smaller,
more focused packages easier to understand and configure, and potentially to
extend as I need.</p>
<p>The other impressive thing about them is that the authors of each of the
packages are talking to each other and trying to make their packages as
inter-operable as possible and also as simple and discrete as possible. The
Marginalia package was extracted from the Consult and Embark packages (which are
maintained by different people), to reduce the overlap between them and ensure
that you can mix and match the different components like Lego bricks to build
your ideal setup. I find this an admirable position, which helps to keep users&rsquo;
options open and improve all the tools. I&rsquo;m going to watch the development of
all these packages with interest.</p>