HOME

M-x apropos Emacs

Table of Contents

Emacs keymaps can have helpful and even dynamic prompts

Published: <2025-07-03 Thu>. Comments on Mastodon.

Nowadays M-o is unbound in Emacs by default, but it used to be used for changing fonts in enriched text mode buffers. Enriched text is what I consider an obscure format that Emacs supports pretty well for some reason. I think rms had hopes of basing some Emacs word processing functionality on enriched text, but I’m a little hazy on the history —which I’d love more knowledgeable people to educate me on. Enriched text (not to be confused with Microsoft’s Rich Text Format) is the MIME text/enriched type defined by internet RFC 1563. In Emacs its supported by the built-in enriched library —see (finder-commentary "enriched").

Now that M-o is unbound by default, I recommend binding it to other-window and turning off repeat-mode for that command with (put 'other-window 'repeat-map nil) so you can switch to another window and type a word starting with “o” without trouble —therwise you wind up with an o-less word in the next window! In fact, I already used that binding back when M-o was used for enriched text fonts.

But enough rambling, the reason I’m talking about this is that back when M-o was bound to facemenu-keymap, pressing it would show this message in the echo area:

Set face: default, bold, italic, l = bold-italic, underline, Other…

That’s right: M-o was bound not to a command, but to a keymap, and pressing it would show a message in the echo area!

One day redditor sebhoagie, asked how to display a dynamic message when a keymap is active, and I had that curiosity about M-o filed away in my brain. I didn’t know what exactly M-o was bound to at that point in time, but I did now it was a keymap, because I had attempted to use C-h c M-o only to have describe-key-briefly wait for more input. So I set out to find out how that keymap did its magic. I ran emacs -q, found out what M-o was bound to by default (recall that I was using it for other-window), and here’s the result (this is mostly what I wrote on reddit back then, with the code modernized a bit):

You can add a prompt for the prefix keymap when you create it, and also prompts for the individual keys bound in the keymap! For example, the following code defines a keymap for package-related operations:

(defvar-keymap pkg-ops-map
  :name "Package"
  "h" '("describe" . describe-package)
  "r" '("reinstall" . package-reinstall)
  "a" '("autoremove" . package-autoremove)
  "d" '("delete" . package-delete)
  "i" '("install" . package-install)
  "l" '("list" . list-packages))

(keymap-global-set "C-c p" pkg-ops-map)

(Here I’m using the recent family of commands, macros and functions for dealing with keymaps, keymap-set and friends from keymap-el, which only accept the key description strings that kbd uses; I recommend these above the older define-key and friends.)

Now, as soon as you press C-c p the following message appears in the echo area:

Packages: list, install, delete, autoremove, reinstall, h = describe

Notice that Emacs cleverly noticed that for the key h you gave the prompt “describe”, which does not start with h, so it actually prints h = describe. The other prompts do start with the letter they are bound to, so Emacs just lists the prompt you gave.

Of course, if you don’t give a prompt for a binding, it’s not mentioned in the overall prompt for the keymap, but the key is still bound. For example, if you replace '("reinstall" . package-reinstall) with a simple 'package-reinstall in the above code, then the prompt will change to:

Packages: list, install, delete, autoremove, h = describe

but r will still be bound to reinstall-package.

Now, sebhoagie said that they had an application in mind for which they wanted the prompt to change dynamically, so this trick wasn’t good enough. And I remember thinking: “Emacs Lisp is super imperative, I bet keymaps are mutable!”. I was right and as a proof of concept I cooked up this little example:

(defvar count 0)

(defvar-keymap counter-map
  :name "Dynamic counter!"
  "i" '("increment" . inc-counter)
  "r" '("reset" . reset-counter))

(defun update-counter-map-prompt ()
  (rplaca (last counter-map) (format "Counter is at %d!" count)))

(defun inc-counter ()
  (interactive)
  (setq count (1+ count))
  (update-counter-map-prompt))

(defun reset-counter ()
  (interactive)
  (setq count 0)
  (update-counter-map-prompt))

(keymap-global-set "<f5>" counter-map)

After running that code, try <f5> i a few times to watch the counter increment or <f5> r to reset it back to zero.

If you are a keymap description you might think you are set for life and just kick back and relax, but you are as rplaca-ble as anyone else.

My quest for completion

Published:<2025-07-01 Tue>. Comments on Mastodon.

This is the entry I would have written for the “Take Two”-themed Emacs carnival if it had taken me less than a month to decide to participate. It’s about all the myriad minibuffer completion UIs I’ve been through as an Emacs user, and is quite long because I’ve tried so many!

Just to make sure we’re on the same page: Emacs commands prompt for user input in the minibuffer and offer completion, which means some sort of assistance typing sensible inputs. There are many possible user interfaces for this in Emacs and I’ve tried many but all of them (By the way, this is a constant in my Emacs usage: I try many but not all of the options, since there are always too many. For example, of the built-in ways to list buffers I’ve used switch-to-buffer, ibuffer, electric-buffer-list and several third party options —I currently use consult-buffer from the Consult package— but I’ve never tried the built-in bs-show, for example. Similarly, of the built-ins I’ve only used GNUS to read email and RSS feeds, but never tried Rmail for email or NewsTicker for RSS; let alone trying all third party options —I did use mu4e for email for a bit and elfeed for RSS feeds!)

Just so this doesn’t take forever to write, I will write it all from memory, and let people correct me on details I get wrong —it’s only fair since I do that to other people all the freaking time (it’s a wonder I have any friends). This list attempts to be in chronological order of my usage, but I’m sure I’m getting some of this slightly wrong (and fortunately no-one is likely to be able to call me out about errors in the ordering of my personal usage of these UIs).

Default completion

In my early days as an Emacs user I simply used the default completion UI. This UI doesn’t not show the completion candidates all the time. If all the candidates have the next bit of text in common, pressing TAB inserts it into the minibuffer (people call this TAB completion). I’ve always found this funny since it makes zero progress towards choosing a single completion candidate: it only inserts as much text as will not narrow down things at all! But people like it for some reason, I guess as visual feedback that what you thought the completion candidates had in common they really do have in common. (To be fair you can configure completion-cycle-threshold to have TAB cycle among candidates when there aren’t many left.)

Pressing TAB a second time will pop up the *Completions* buffer, which shows a list of all completion candidates. From there you can click on a candidates, navigate to it and press RET, or just type some more and press TAB again to get an updated candidate list.

Don’t knock the default completion UI. It is functional, powerful and perfectly usable out of the box. But most people want to see how the available candidates change automatically as you type. The other UIs I tried all have that feature in common; they also all have a notion of the “current completion candidate”, and there is a way to select that current candidate without finishing typing it —usually but not always this done simply by pressing RET.

Ido

Ido also comes with Emacs and is pretty funky. For one thing it doesn’t take over all minibuffer completion services, it only provides special versions of certain commands, mainly to open files and switch buffers. Those commands also enable some additional key bindings while you are using the commands: while opening a file you can press a key to delete a file, or while switching buffers you can press a key to kill a buffer. This sort of thing is called “acting on a completion candidate”, and boy do I like it —more about this later. Ido uses fuzzy completion, where characters only have to appear in order in a completion candidate, not necessarily consecutively; for example epnf matches eww-open-file.

If you like Ido but want to use it for all minibuffer completion there are some options: there’s the ido-completing-read+ package and the built-in fido-mode. I don’t particularly like fuzzy matching since it feels inefficient to me, there are always two many matches for my taste.

Helm

Helm is a comprehensive package that not only takes over all minibuffer completion duties but comes with many commands that take advantage of Helm’s additional features. It’s big and brash and opinionated. I used it for many months and was quite happy with it. I particularly liked that the Helm commands came with many actions you could perform on the completion candidates. I didn’t much like its default aesthetics or its long load time (although since you only incur that once per session it doesn’t really matter). One thing I didn’t like much is that somehow it didn’t seem to blend in very well with the rest of my Emacs experience. For example, only commands written specially to use Helm had actions for the completion candidates, and the actions had to be implemented in a particular way, you couldn’t use any old Emacs command as an action. But all in all Helm is great, an impressive piece of software that sprouted its own mini-ecosystem of related packages.

Ivy

After Helm I used Ivy and its companion Swiper and Counsel packages for a while. It felt pretty similar to using Helm to me, except I liked the default look of it better (which is not to say you couldn’t easily configure the visual aspects of Helm). It also had a notion of actions, but similarly to Helm, you needed to write them specially for each command. I think it was less batteries-included than Helm, for example I have a vague recollection of counsel-find-file, its substitute for find-file, not coming with actions to rename or copy files, which I wrote in my own configuration. It’s then that it started to bother me that I couldn’t simply say “I want the Emacs commands rename-file and copy-file as actions”, I was forced to write little wrappers for them. Like Helm, I think the Ivy/Swiper/Counsel family is great software and was a happy user. I did however, as I did with Helm, that it reinvented the wheel too much and that something like it would be possible that took more advantage of existing Emacs APIs and functions.

Icomplete

This is another built-in option, which I think I only started using after having used Helm and Ivy. I used it for a quite a while and still think it is perfectly workable. One thing I like about it is that, like the default completion UI, it only concerns itself with displaying the completion candidates and leaves the important matter of which candidates are considered to match the minibuffer input to the current completion styles. There is no formal notion in Emacs of a “well-behaved” completion UI, but in my head certainly such a UI should limit itself to showing you the candidates and leave the user to configure completion styles separately. This what I dislike about fido-mode: it ignores your completion style configuration and makes you use the flex completion style instead (you can change this but it requires being sneaky, not simply setting completion-styles).

One difference between Icomplete and Helm or Ivy, is that it displays the completion candidates in a compact horizontal list like Ido, instead of one per line, like Helm or Ivy. When I was an Icomplete user, I even wrote a package called icomplete-vertical that would configure Icomplete to display the candidates vertically, one per line. Nowadays there is also a built-in package of the same name which I did not write, nor does it use my code. I remember thinking the built-in package had a bug mine lacked, triggered when you switched from horizontal to vertical during a minibuffer completion session, but I couldn’t reproduce it now so either they fixed it, or I couldn’t remember exactly what the bug was, or my memory is playing tricks on me.

live-completions

The mention of icomplete-vertical above is the start of an embarrassing parade of completion UIs I wrote myself, for myself and which I don’t think more than a handful people ever used. What marred all of my feeble attempts, other than icomplete-vertical which is just some configuration code on top of icomplete, was a distinct lack of speed. The idea of these incremental, automatic completion UIs is to show you how the candidate list changes in real time, but most of mine struggled to do this fast enough.

My live-completions package had a very simple idea: pop up the *Completions* buffer that the default UI uses and just update it after every key press. It let you format the completions in either a grid or a single column, back before the default UI had the single column view.

I think I used this for quite a while though it wasn’t very good. I believe that by the time I wrote this, I already had an initial version of Embark that took care of acting on completion candidates solving all of the complaints I had about actions in Ido, Helm or Ivy: Embark lets you use any Emacs command directly as an action, there is no need to write wrappers over existing commands; it endows every single command that has a minibuffer prompt with actions on its candidates, commands do not have to be written specially with Embark in mind to acquire actions.

grille

Another bad completion UI I wrote. Hey, at least it’s small. I don’t think I used this for very long, maybe a couple of weeks. It’s called grille because it displays completions in a grid. I have nothing else to say about it.

embark-completions

For a while Embark included its own completions UI! This is obviously a bad idea, which I only did because it was easy, since Embark had grown to have almost all the components necessary for this. It was slow, but other than that I found it surprisingly good. It was certainly featureful: it displayed the completions either one per line or in a grid, the grid optionally with zebra stripes to guide the eye. I stubbornly kept using it until I dropped it for Vertico and finally removed it from Embark.

Vertico

The excellent Vertico package is what I use now as a completion UI. The author, Daniel Mendler, and I have long worked together on a suite of packages that provide a full completion experience for Emacs. I wanted to switch from embark-completions to Vertico but held out until Daniel added a grid display to Vertico. In retrospect this was silly on my part, but I believe my stubbornness might have helped motivate Daniel to add the grid feature. Of this suite of packages, Daniel wrote Vertico, Corfu, Cape; I wrote Embark and Orderless (the latter of which we now co-maintain); and we wrote Marginalia together after noticing we were both writing something like it.

Vertico
a highly flexible completion UI, that can display completions one per line or in a grid, in the minibuffer or in a dedicated buffer.
Orderless
a highly configurable completion style, whose main feature is matching space-separated bits of the input in any order against the completion candidates; so op eww matches eww-open-file.
Embark
lets you use any Emacs command as an action on any minibuffer completion candidate or on a thing at point in a non-mini buffer; it also comes with an extensive default configuration assigning convenient keybindings to the most commonly used actions (but you can always M-x to use whatever command you want as an action!)
Marginalia
provides extra information about completion candidates of common types, most completion UIs that display candidates as one per line will shows this extra information to the right of the candidate.
Corfu
this is a completion UI for completion-at-point, which I haven’t talked about here at all —it is the type of completion that you get when writing code in a buffer, for example. Again here I stubbornly held out a long time using my own contraption (consult-completion-in-region, which I contributed to consult).
Cape
a suite of completion-at-point functions; again I stubbornly held out using an embark-based substitute for this for a long time —I’m starting to notice an unflattering pattern.

Selectrum and MCT

I already finished listing the completion UIs that I actually used for a period of time, but there are a couple of others I tried and probably some I did not try (maybe snails, though I’m not exactly sure what it is, since I’ve only every briefly skimmed its README). I tried Selectrum once and, to my discredit, only complained about some minor issues with it on reddit. At least I’m focused thematically in my complaints: I thought it wasn’t Emacsy enough, that it disrespected some Emacs variables it could easily respect. Well, that, and there something I didn’t like about its completing-read-multiple experience (I think it was that you couldn’t easily see what you had already selected). I never used Prot’s MCT package extensively, but I would call it similar in idea to my live-completions package, and would hope Prot does not disagree with this characterization. It somehow seemed smoother than my live-completions, probably because Prot had more patience tweaking the experience than I did.

Welcome to M-x apropos Emacs

Published:<2025-07-01 Tue>.

Recently Christian Tietze called for Emacs blog posts with the topic “Take Two”, meaning things that took two or more tries to get right. He also said:

Don’t have a blog, yet?

Well, just start one already! :)

It’s the future of the internet!

I mulled over this the whole month and finally decided to start a blog about Emacs just in time to miss that first round of the Emacs carnival! (I’m likely to miss deadlines like that again in the future.)

Now, about twenty years ago, when blogs did actually seem like the future of the internet, I had one on a hosted service. I think I may have started on Blogspot, but then moved to Wordpress.com. It was a personal blog about whatever random topic I wanted to write about. I did not write very frequently on that blog, and am unlikely to write often here either, although maybe constraining the topic to Emacs might inspire me more than having no constraints did.

I was already an Emacs user back then, but I wasn’t as gung-ho about it as now, and back then I meekly accepted Wordpress making all sorts of decisions for me, which seems cowardly today; so I definitely want a more Emacsy way to write this new blog. I figure all a blog needs is a publicly accessible web page and a publicly accessible RSS feed. An important optional component is a system for comments. So, to do the easiest thing possible, I will write my blog in a single Org file (for now, I’ll manually paginate if it turns out I do keep it up!), use ox-rss to create an RSS feed, and for comments I’ll just use Mastodon.

Since I threw this together in about ten minutes, I’m sure there will be bugs. I probably don’t have permalinks correct at all.

Omar Antolín Camarena