Emacs: Completion And Function Bundles (publ. 2024-03-15)

Something has worked very well for me, due to the rapidity of calling commands through fuzzy completion, is to wrap simple tasks in Emacs functions with descriptive names. This is particularly convenient due to the availability of the shell-command and async-shell-command functions, which allow me to call any command that I would normally call in a shell. E.g.:

Then M-x filesystem-size gives

Where this starts to become cumbersome, however, is if we have a lot of very similar functions. We want some way to group them. E.g., one helpful application is a function that calls browse-url-xdg-open multiple times to quickly open a bundle of Web pages in the Web browser:

This function opens four weather-related Web pages at the same time. Very convenient. But what if we want another function that opens news-related Web pages, and another function that opens work-related Web pages, and so on? I want some kind of grouping.

One solution is Emacs' transient system, where calling a command gets you a page with keypress shortcuts. But, I don't like that. I want to deal with easy to remember words and phrases, not single letters attached to commands.

I want to keep calling commands like I am already doing, while holding onto the convenience of completion. Thankfully completion, including helm completion, is tied into the completing-read function:

(completing-read PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH
INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)
Read a string in the minibuffer, with completion.
PROMPT is a string to prompt with; normally it ends in a colon and a space.
COLLECTION can be a list of strings, an alist, an obarray or a hash table.
COLLECTION can also be a function to do the completion itself.
PREDICATE limits completion to a subset of COLLECTION.

Basically, we can just call this function anywhere — passing it a list of possible keys — and it will prompt the user, along with completion — built-in completion, helm completion, or anything else that is layered on top of it. It can take an association list as well, which will prove convenient.

I pushed forward with the idea of having "bundles" of functions, which are just association lists with keywords for the car and lambdas for the cdr. I have one general function that takes a bundle, prompts the user, and then calls the appropriate function from the bundle.

Here is a bundle I have right now, with one helper function:

The advantage here of using lambdas, instead of just having URLs that are processed, is it allows me to insert more advanced functionality when needed, like the open-foi-news-digest function used above, which I have mentioned previously:

And here is the top-level function for the web pages bundle:

This approach is quite simple and easy to use, assuming we are comfortable with basic elisp. I'm thinking it might be nice though to add some syntax — via macro — to make building the function bundle a little cleaner. And maybe another macro for making the top level function. Or maybe one macro that does both.

This work © 2024 by Christopher Howard is licensed under Attribution-ShareAlike 4.0 International.

CC BY-SA 4.0 Deed

Proxied content from gemini://gem.librehacker.com/gemlog/starlog/20240315-0.gmi

Gemini request details:

Original URL
gemini://gem.librehacker.com/gemlog/starlog/20240315-0.gmi
Status code
Success
Meta
text/gemini
Proxied by
kineto

Be advised that no attempt was made to verify the remote SSL certificate.