A Year or So of Emacs

Swapping out Ivy for Selectrum

Jakub Kadlčík FrostyX.cz wrote A Year with Emacs. on /r/emacs, someone asked How much time you need to spent with Emacs to become more productive?

All of this reminds me that I’m coming upon my first anniversary of adopting Emacs 🔍. According to my configuration log entry It looks like is my Emacs anniversary. I have no idea how that was my first “commit” for Emacs. But in the days prior, I was committing changes to configure my Visual Studio Code (VS Code 🔍) installation, so we’ll go with . I have long since uninstalled VS Code and Atom text editor (Atom 🔍).

Earlier I wrote about , and I’ve changed a few things. Instead of using Ivy/Counsel/Swiper, I’m now using Selectrum/Consult.

Switching from Ivy to Selectrum

During my first year of Emacs, I’ve started following Sacha Chau’s blog. This includes Emacs News. And I’ve joined /r/emacs and /r/planetemacs. A common thread is tips and tricks that people have used to further configure Emacs to their needs or as a challenge/exercise for themselves.

I had initially settled on Ivy and Swiper and Counsel for search enhancements. And I experimented with Helm et al including Helm Swoop)

In , I learned about Selectrum and then Embark.

As I read about Selectrum, I honed in on two sections:

The focus of Selectrum is on providing an enhanced completion UI and compose with other packages which stay within the constraints of the standard Emacs API.

Ivy is a promising alternative to Selectrum. It is described as a minimal alternative to Helm which provides a simpler interface. The problem with Ivy is that its architecture and API have grown organically, and as a result the implementation is complex. Ivy was originally designed to be used as a backend to Swiper, a buffer search package that originally used Helm. When Ivy became a more general-purpose interactive selection package, more and more special cases were added to try to make various commands work properly. As a result, the ivy-read API is complex with around 20 arguments and multiple special cases for particular values. Numerous functions in Ivy, Counsel, and Swiper have special cases hardcoded into them to detect when they’re being called from specific other functions in the other two packages.

What caught my eye is Selectrum’s cleaving close to the Emacs Application Programming Interface (API 🔍) and that Ivy has expanded in scope. In my experience this means that Ivy will be harder to maintain/extend/support compared to Selectrum. Note: I’m looking at scopes of 5+ years, as I intend for Emacs to be my editor of choice until I’m no longer using a computer.

That difference prompted me to explore what would it take to switch?

First, I clarified what I wanted. The primary feature was Swiper-like behavior. I use Swiper all the time to orient to the contents of a buffer. I found consult-line to be a great replacement. consult-line comes from the Consult package

Other behaviors that I’ve found useful is Counsel edit mode and wgrep-ag.

With those features in mind, I began my refactor.

I went through my Emacs configuration, and gathered up all of the declarations I had for using Ivy, Swiper, and Counsel. I moved those into a file. Then restarted Emacs. And “everything” worked. I removed the require for that file, and nothing broke on initialization. This gave me enough confidence to say was successful in isolating those packages and packages that depended on them.

You can see that file in in my emacs/jnf-ivy.el file. Also, I did all of this rework with Git (git 🔍) commits. Thus, if I broke something, I could rollback.

With Ivy et al isolated, I created emacs/jnf-selectrum.el and started configuring/building the replacement.

At one point, during the replacement, I decided to halt work and go back to Ivy. I wasn’t yet convinced that this puttering on my Emacs config was worthwhile. Later, I picked up the work and completed the cutover.

I tested the replacement by removing the require for jnf-ivy.el and adding a require for jnf-selectrum.el. With some poking and prodding, I was mostly up and running. And to verify the isolation, I removed the require for jnf-selectrum.el and nothing broke during Emacs initialization. So I had successfully compartmentalized both the Ivy and Selectrum ecosystem.

A few things in the Selectrum / Consult ecosystem that I love:

Preview of Buffers

For most of the buffer oriented features (e.g., consult-bookmark, consult-buffer, etc.), when the mini-buffer opens and you select a different entry, the original window shows the file. A nice helper when you’re looking to change context.

Embark Export

The embark-export function, similar to Ivy’s occur, opens a new buffer with the current mini-buffer results. From there I can use wgrep to edit lines from other files. All within the original mini-buffer context.

Consult Yank

The consult-yank function is one that’s on probation. I might like it, but am continuing to try it out. The consult-yank function wraps yank but provides a minibuffer preview of what you would be yanking back into the buffer. The hiccup, is you need to confirm the consult-yank.

As a long-time user of Jumpcut, I like the ability to preview what I’m about to paste, and be able to select from the history of copy/cut calls.

Further Delves into Elisp

I’ve been programming for years, and have preivouly dabbled with Lisp 🔍. It’s different, but in the last month, Elisp 🔍 started feeling quite natural.

I’ve written about , and extended Emacs to conform to my note taking, blogging, software development, Rich Site Summary (RSS 🔍) reader, and PDF 🔍 annotator. These days, I look at “What am I doing outside of Emacs that I might be able to better incorporate into Emacs?”

I wrote an advice-add function that mirrored a feature I found in Helm Swoop. Namely, when you initiate consult-line, if you’ve highlighted text, it will use that for the initial filter. Otherwise, it will use the word at point.

(advice-add #'consult-line
            :around
            #'jnf/consult-line
            '((name . "wrapper")))

(defun jnf/consult-line (consult-line-function &rest rest)
  "Advising function around `CONSULT-LINE-FUNCTION'.

When there's an active region, use that as the first parameter
for `CONSULT-LINE-FUNCTION'.  Otherwise, use the current word as
the first parameter.  This function handles the `REST' of the
parameters."
  (interactive)
  (if (use-region-p)
      (apply consult-line-function
        (buffer-substring (region-beginning) (region-end)) rest)
      (apply consult-line-function
        (thing-at-point 'word) rest)))

Conclusion

With my Emacs config are little changes I’ve made to make Emacs better fit my approaches. I’m also

Emacs feels like an ecosystem that is defiant of corporate Embrace, Extend, and Extingush approaches. I look to The Open-Source Software bubble that is and the blogging bubble that was, and am thankful I continue blogging and use a Free Open Source Software (FOSS 🔍) text editor that’s not actively a part of Google, Microsoft, Facebook, Amazon, nor Apple’s full-blown extraction efforts.

My plan with Emacs is to engage with the community of practioners and provide what help I can. I’m not an expert, but I’m more experienced than some of us using Emacs.

update

I had nor have no current problems with Ivy/Swiper/Counsel (ISC). I think they’re great tools. What I found is that Selectrum/Consult/Embark (SCE) covered how I used ISC. There may be additional functionality of ISC that I’m missing out on, or don’t know exist.

So, given that my desired feature set exists in ISC and SCE, then I started looking at package size and surface area of functionality. In my experience, the larger that surface area the more effort will be required to maintain it. Which isn’t to say that that effort won’t be applied, it’s instead framing that as a risk.

And in taking the time to test and use both, I’m in a better position to be more specific in why I’m using the package.