HOME

M-x apropos Emacs

Table of Contents

Ten things to try with Embark

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

This is my first listicle! (I apologize in advance for it, and hope not to do this too often.) Here are 10 not-so-obvious things to try with Embark, written as a response to this reddit question.

I’ll use <act> to represent whatever key binding you have for embark-act, and <dwim> to denote the binding for embark-dwim.

  1. If I’m looking at some project’s README file and it mentions some command I should run (for example, to install the project), I don’t copy the command, start or switch to a shell, and then paste the command. Instead I select the command, and use <act> M-! (or <act> M-&) to directly pass the command to shell-command (or async-shell-command). Notice that M-! is just the global binding for shell-command. In embark you can use any command as an action, you are not limited to the commands in the embark keymaps (those keymaps are just for convenience); you can specify the command with any key binding you have for it, or even by using M-x. (I’ve been asked more than once to remove this freedom and limit users to pre-registered commands from the embark keymaps, which seems insane to me, and I refused all such requests!)
  2. I use jinx for spellchecking in both English and Spanish, and sometimes I want to add a word (usually a proper name) to my personal dictionaries for both languages. To do that I take advantage of the fact that while jinx-correct is running, that is the default action, i.e., embark-dwim will run jinx-correct. So if I have embark-quit-after-action set to nil (which I prefer), I can add the word to one dictionary using <dwim> instead of RET, and this keeps jinx-correct open so I can still add it to the other dictionary (this time using RET, so jinx-correct now finishes).
  3. Similarly to the previous example, when writing an email I can run mml-attach-file and use embark-dwim to attach several files in one go. This is useful because I often need to attach several files from the same directory, and using a single run of mml-attach-file saves me from having to navigate several times to the directory. In fact, often the files I need to attach all have something in common in their name, say, I need to send all files of the form report-$MONTH-2025.pdf. Then I can run mml-attach-file, navigate to the directory containing them, type report 2025, which under Orderless will match exactly the files I want, and then run <act> A RET, which will run the default action (attaching) on all of them.
  4. If I’m reading Emacs’s info documentation, and it mentions some command I want to try, I put point on the command name and use <act> x (for commands, x is bound to execute-extended-command). If it mentions some variable and I want to customize it, <act> u (for variables, u is bound to customize-variable). I used to copy and paste a lot more, to get inputs to commands, but Embark let’s me send things directly to the commands that use them.
  5. Any command that prompts for widgets becomes a widget manager! For example, I use dired a lot less than I used to, since I now do most of my file management from inside find-file: I use embark-act from inside find-file to delete, rename, copy, or open files with external programs. Similarly, I do most package management from inside describe-package, using embark-act to install, uninstall, view the homepage or description for a package. Similarly, if I want to toggle, customize, or find out the current value of a variable, I’ll do it from describe-variable. I use find-library not just to open a library, but also to load one, or to view the commentary or info manual. I only need to remember (or even have) the key bindings for the commands I use as entry points, and Embark reminds me of the rest.
  6. If see you some arithmetic operations written in a buffer somewhere, you can print the result in the echo area by selecting that text and sending it to quick-calc with <act> C-x * q (if you do this often, you might want a better keybinding for quick-calc than the default C-x * q). With a universal prefix argument, quick-calc will insert the result in the buffer instead of just echoing it; I used this to compute that 30! = 265252859812191058636308480000000. Similarly if you want to add a column of numbers, select the numbers and use <act> : (for regions, : is bound to calc-grab-sum-down).
  7. I even use <dwim> instead of C-x C-e to evaluate expressions for several reasons: (1) my keybinding for embark-dwim is shorter than C-x C-e, (2) I can place point either before the opening parenthesis or after the closing one (or even use <act> from anywhere in the middle of the s-expression and cycle to the s-expression target), (3) the default action in Embark for s-expressions is pp-eval-expression, so you get pretty-printing too! Another nice action on s-expressions is embark-eval-replace (bound to <), which replaces the s-expression with its value.
  8. Sometimes I’ll use M-! to run a shell command and while I’m typing the full command realize I forgot exactly how you use the program (maybe I forgot what an option is called, or the order of the arguments), in that case, I put point on the command name and run <act> M-x man to pop up the man page while I keep working on typing in the command.
  9. Embark tries to use the same key binding for conceptually similar actions. For example h is describe-symbol, describe-face, finder-commentary, or describe-package depending on what you act on. I try to extend that as much as possible in my personal configuration. For identifiers in programming modes that are not Emacs Lisp, Embark binds h to display-local-help, which isn’t very useful on its own, but you can remap it to something better, For example, in shell script buffers (and in shell buffers) I remap display-local-help to man, and in perl-mode buffers I remap it to cperl-perldoc. That way I can still get help for the thing at point with <act> h in those buffers.
  10. I use org-ql-find or consult-org-heading to search my org files and I use embark-act to do things to the headings right from the minibuffer without losing my place. Particularly useful are I and O which are bound to org-clock-in and org-clock-out. To link to a heading, I used to navigate to the heading, use org-store-link, navigate back to where I wanted the link (usually easy by popping the global mark) and then use org-insert-link. But now, I just search for the heading I want to link to with org-ql or consult, and use <act> j to insert the link, it’s super fast and convenient, and I find myself interlinking my notes much more now (I guess this is one of the things people like about org-roam, too). Similarly if I want to link to a bunch of headings I can usually craft and org-ql query that matches exactly the ones I want, then I use <act> A l, to call embark-act-all with org-store-link as the action, and finally I use org-insert-all-links to insert all links as an itemized list.

Writing Experience

Published: [2025-07-21 Mon]. Comments on Mastodon.

This blog entry is part of the Emacs Carnival for July 2025, hosted by Greg Newman, with the topic of “Writing Experience”.

I mostly use Emacs to write prose, not because I don’t also use Emacs to write computer programs, but simply because I write a whole lot more prose than code! I write papers, lecture notes, homework assignments, notes on different topics (some public, some private), my website including this blog, emails, comments on social networks, and I’m even supposed to be keeping a journal (though I notice the most recent entry is from April…).

But more than that, I tend to write any bit of text longer than a sentence or two in Emacs. The main the reason for that is that I edit a lot as I write and Emacs makes this easier than any other text editor I’m aware of. Before Emacs I used Vim and, while it is a very powerful text editor, it has distinct modes for inserting text (called insert mode, naturally) and for editing it (called normal mode, to mock writers for being imperfect and normally requiring editing). The separation of modes nudges you in the direction of getting a first rough draft down and then editing it. That suits some people perfectly, and it is certainly something I could do and was used to, but I think that I am naturally more of an edit-as-you-go person. My evidence for this is that it is what I do in Emacs, which favors neither the draft-first nor the edit-as-you-go style ―it’s pretty much the same number of keystrokes either way, unlike in Vim where you give the poor ESC key a break if you batch your edits.

By the way, the fact that I spend so much time editing prose is also why I need a text editor like Emacs or Vim and couldn’t switch to a code editor like VS Code. When an editor calls itself a “code editor”, my impression is that it does so to signal poor support for prose (or maybe it wants to signal good support for code ―I needn’t be so negative). I don’t think VS Code has commands to move by or select sentences, for example; instead it’s line-oriented, which makes sense for programming ―or, I guess, for people who write prose one sentence per line because they use git and want cleaner diffs but don’t know about git diff --word-diff.

Emacs is very powerful out of the box for editing prose, but even so I have a few personal tweaks to make it fit me like a glove. In the rest of this blog post I will describe a few commands I use when editing prose, some built-in, some I wrote myself to scratch a small but persistent itch.

Changing case and transposing

One of my most common typos is being slow to release the shift key and accidentally capitalizing the first two letters of a word, as in “See you next THursday!”. When I make that mistake I often notice it before I finish typing that word and in stock Emacs I could fix it right away with M-- M-c or M-b M-c. (By default M-c is bound to capitalize-word, but I recommend rebinding it to capitalize-dwim which acts as capitalize-word unless there is an active region in which case it acts as capitalize-region.) At some point I noticed that my most common use of M-c was to capitalize the previous word, and decided to simplify that case. Initially I wrote a command that is just like capitalize-dwim except that if point is at the end of the word it acts on the previous word rather than on the next one. That did simplify my most common usage of M-c but it introduced a new problem: when I wasn’t fixing a typo in a word I just entered, I often forgot the new behavior and expected M-c to capitalize the next word, even if point was at the end of a word; in those cases my new command annoyed me quite a bit.

This illustrates what I feel is an underappreciated point: the user experience (UX) of even simple editing commands is often tricky to get exactly right. Of course, people are aware that UX design is hard, but I think people tend to assume it’s only hard for larger programs, not for something tiny like capitalize-word. But for a command you are likely to use many times a day getting the UX exactly right really pays off. I eventually fixed my command drawing inspiration from a different set of commands that are also extremely useful while writing prose: the tranpose family of commands. I’ll explain the feature of these commands that I adopted for the case change commands, after I explain what they do. The transpose commands are fantastic and I don’t understand why not every editor has them (even Vim doesn’t!). Another extremely common typo I make is swapping two charcaters. To fix that, you put point on the second of the characters (if your cursor is a bar, put the bar between the swapped characters) and use transpose-chars, bound by default to C-t. There are also tranpose-words (M-t), transpose-sexps (C-M-t), transpose-lines (C-x C-t), transpose-sentences and transpose-paragraphs. The sexp and line commands are more useful for editing code than prose, but are still useful for prose, particular since parenthetical expressions or quoted text count as sexps. It’s a little sad that the sentence and paragraph commands are not bound by default; I bind them to M-T and C-x M-t respectively. While transpose-chars is most useful for fixing typos, the other transpose commands are more useful while editing. I find I rearrange text quite a bit: Even for a 5−10 line email I’m fairly likely to have swapped two sentences or even two paragraphs while writing it!

The transpose family of commands have a few very nifty features:

  1. They leave point after the second of the two swapped things, which means that by simply repeating the command you can continue to move that thing to the right. With a negative prefix argument you can drag things to the left instead.
  2. With a prefix argument of 0 they can swap non-adjacent things! Select a region starting somewhere in the first thing and ending somewhere in the second and call a transpose command with a prefix argument of 0 to swap them,
  3. If you use transpose-chars at the end of a line you might think it would swap the last character of the line with the newline, since, that newline is after all the next character, but instead it swaps the last two characters on the line. This means that if you accidentally swap two characters while entering text (at the end of some line) and notice the typo immediately, you can fix it with just C-t without moving the point! This is special behavior of transpose-chars, sadly not shared by transpose-words, but at least that one has a similar but lesser magic: if you use transpose-words at the end of the buffer (yes, I said “buffer”, not “line”), it will… not swap the last two words, but produce an error message. and also move point to before the last word. But that very last bit means that a second M-t will swap the last two words! OK, kind of lame compared to C-t but at least it’s something.

That last behavior of transpose-chars is what I adopted for my versions of the case-change dwim commands: if you call one of my case-change commands at the end of a line, it changes the case of the last word of the line (not the first word on the next non-blank line, which is what capitalize-word or capitalize-dwim would do). And that feels perfect to me: my common typo is fixed with a simply M-c but while editing text in the middle of the text I don’t get any unpleasant surprises anymore. Try teaching that to a web browser text input box!

Marking whole words

Another tiny annoyance I had with the built-in commands is that the marking commands only mark from point to the end of the thing they are for. For example mark-word does not mark the word at point, it marks the portion of that word starting at point (so if point is on the first character of the word, it does mark the entire word). The analogous command for sentences has more honest name: mark-end-of-sentence ―though mark-to-end-of-sentence would be even clearer. Now, for sentences, that behavior seems fine and useful to me, since I often do want to grab just the tail of a sentence, but I basically never want to mark just a piece of a word. So I wrote a command that marks the entire word point is on, bound it to M-@ and just use it in place of mark-word. Obviously I called my command mark-my-word.

Useful commands with no default key binding

That mark-end-of-sentence command I mentioned doesn’t have a default key binding, but that’s OK since you can achieve the same effect by using shift selection with the forward-sentence command (I mean typing M-E). But there are some very useful commands, particularly in the misc.el library, with no key binding:

  • zap-up-to-char, which I find I want more often than zap-to-char, so I bind this one M-z and zap-to-char to M-Z.
  • forward-to-word and backward-to-word which move to the opposite end of the word than forward-word and backward-word do; I bind these to M-F and M-B.
  • copy-from-above-command and duplicate-dwim, two commands that can duplicate a line. The first duplicates the line above point and the second duplicates the line at point. The first command actually duplicates the tail of the line above starting from the current column, and if given a numeric argument will only duplicate that many characters (I hardly ever use this last bit of functionality since I find counting characters tedious and error prone). The second command will duplicate the region if it is active ―which is what dwim means in several Emacs commands.
  • delete-forward-char is a surprising one: by default C-d is bound to delete-char but the documentation for that command says: “The command ‘delete-forward-char’ is preferable for interactive use, e.g. because it respects values of ‘delete-active-region’ and ‘overwrite-mode’.” I agreed and rebound C-d.
  • kill-paragraph, I bind this to M-K.
  • up-list moves you out of a delimited expression, which honestly is more useful when writing code, but I mention it here since I do use it often for getting out of parenthetical remarks or quotation marks. I bind to C-M-o which goes well with the other sexp navigation commands with C-M- modifiers; the mnemonic for o is that it gets me Out of a sexp.
  • transpose-sentences and transpose-paragraphs I already mentioned above. I bind them to M-T and C-x M-t. In org-mode buffers you don’t really need transpose-paragraphs since M-<down> and M-<up> cover its functionality.

Dabbrev

The kind of “autocompletion” I almost always want while writing prose is simply to complete text I’ve already typed somewhere. For that dabbrev-expand (bound to M-/) is super useful: it’ll search for completions of the beginning of a word you’ve typed in several places in order: the current buffer before point, the current buffer after point, other buffers in the same major mode as the current buffer, and finally all other buffers. (That’s just the default configuration, as usual in Emacs, dabbrev is quite configurable.) I often find myself opening some file just so I can complete words from it in another buffer. One lesser known feature of dabbrev-expand is that you can also use it to complete phrases, not just words: if right after completing a word using dabbrev-expand you insert a space and then run dabbrev-expand again, it will insert the word that followed the first word wherever it found it. So M-/ SPC M-/ SPC M-/ ... will complete a phrase from your buffer. To make this even more convenient I wrote this little command that I bind to M-;:

(defun dabbrev-next (arg)
  "Insert the next ARG words from where previous expansion was found."
  (interactive "p")
  (dotimes (_ arg)
    (insert " ")
    (dabbrev-expand 1))
  (setq this-command 'dabbrev-expand))

That way I can complete a phrase with M-/ M-; M-; .... You can really fly that way. For example, the previous paragraph says “current buffer” three times; I only wrote the first one in full, the others were cur M-/ M-;.

Ediff

This one isn’t so impressive to computer programmers, used as they are to source control, but let me tell you that the ease with which you can merge versions of files using ediff will absolutely blow mathematicians minds! I’ve impressed several coauthors by merging our changes to a draft paper in less than a minute, flying over changes faster than they can orient themselves. It feels like a super power to people who haven’t seen something like it before.

Keyboard macros

I don’t think it would surprise anyone to say that keyboard macros are very useful for automating edits while coding, but perhaps it is a little surprising they can also be very useful while editing prose. One thing that comes up fairly often for me is that I want to write a bulleted list and I have the raw data I need to talk about in some other format. For example I might have a spreadsheet (if it’s shared) or an org table (if I’m the only one editing) with a list of names, email addresses and affiliations of some people and I need to write a small paragraph about each person. Here’s an example with fake people:

Juana Sinisterra jsinis@uni.junco Universidad del Junco
Molly Edwards medwards@henkin.edu Henkin College
Mario Finetti mfino@vallebruna.it Universitá di Vallebruna

And I want to turn it into:

  • Juana Sinisterra <jsinis@uni.junco> from Universidad del Junco, XXX.
  • Molly Edwards <medwards@henkin.edu> from Henkin College, XXX.
  • Mario Finetti <mfino@vallebruna.it> from Universitá di Vallebruna, XXX.

where the “XXX” are placeholders I’ll fill in later. (I’d actually use <++> as the placeholders and fill them in using my placeholder package, but never mind that now.) For this I’d record a keyboard macro that transforms a single row of the table and just run it for each line. For dealing with keyboard macros I prefer the “modern” interface, consisting of kmacro-start-macro-or-insert-counter (bound to <f3>) and kmacro-end-or-call-macro (bound to <f4>), which can be used in place of all four of these “old” key bindings: C-x (, C-x C-k C-i, C-x ) and C-x e. However I find the function keys a little too far for comfort, so I rebind the commands to M-r (for “record”) and M-m (for “macro”). (M-m is bound by default to back-to-indentation, a command which I do use but rebound to the more mnemonic M-i; M-r also has a default binding, but I never use that command). Since I switched to the simpler “modern” macro commands I find that I use keyboard macros a lot more, and rebinding them to the highly accesible M-r and M-m keys gave my macro usage a further boost.

In the example I gave above, I wanted to run the keyboard macro to every line of a table. You can do that by recording the macro, marking the remaining lines and using apply-macro-to-region-lines bound to C-x C-k r. That key binding is a little awkward and to be honest I don’t use it: Embark binds that command to m when you are acting on a region, so I use C-. m (simpler key bindings are a nice perk of Embark’s contextuality). But there is further convenience to be enjoyed: as in this example, I very often want to apply a macro to every line of a “paragraph” (a table with a blank line after it counts), or rather, to the remaining lines of a paragraph after recording the macro for the first line. For that I wrote this simple command I bind to M-M:

(defun apply-macro-to-rest-of-paragraph ()
  "Apply last keyboard macro to each line in the rest of the current paragraph."
  (interactive)
  (when defining-kbd-macro (kmacro-end-macro nil))
  (apply-macro-to-region-lines
   (line-beginning-position 2)
   (save-excursion (end-of-paragraph-text) (point))))

It feels like magic: M-r, do stuff to the first line, M-M and boom, the same transformation gets applied to the rest of the lines!

The case against which-key: a polemic

Published: <2025-07-04 Fri>. Comments on Mastodon.

It’s Friday and jcs over at Irreal has started a tradition of being polemical on what he calls Red Meat Fridays. I’m joining in on the fun today to explain why I don’t like which-key ―but going somewhat against the red meat spirit I don’t want to merely criticize: I’ll offer up a suggestion of something better at the end, too.

What which-key-mode does is popup in the echo area a list of key bindings and commands found under the current prefix. Here’s what it looks like after I pressed C-x C-k waited a second for the popup to appear:

which-key-example.png

Since the commands under C-x C-k didn’t all fit on a single page, which-key splits them into multiple pages and you can advance through them with C-h n and C-h p. Reading through the which-key popup is a great way to learn what is bound under a prefix. People love this and which-key is now bundled with Emacs.

So why don’t I like it? There’s a minor reason and a major reason. The minor reason is simply that it is automatic by default. The default configuration has the which-key popup appear 1 second after typing a prefix. Some people love this because it pops up precisely when they don’t know or can’t remember what key to press next. I dislike almost all forms of automatically appearing UI finding them jittery and distracting; I almost always prefer to summon UI explicitly with a key press or maybe mouse action. I understand this only a personal preference, and it is an easily fixed one at that! There is a simple way to configure which-key to wait for you to type C-h to appear:

(setq which-key-show-early-on-C-h t
      which-key-idle-delay 1e6 ; 11 days
      which-key-idle-secondary-delay 0.05)

So that was just a small matter of personal preference, what’s the major reason at the heart of this polemic then? It is this: I believe we should use computers for automation, to assist us in finding information. Clearly which-key-mode has a different philosophy: it merely displays all the key bindings under a prefix and then lets humans do all the work! A human has to read the key bindings, possibly paging through a couple of pages them. It feels ridiculously to be sitting at a computer, a very powerful information retrieval machine, equipped with a high bandwidth input device (namely: a keyboard) and to read a bunch of boring text as if it were printed on a piece of paper (or two or sometimes even three pieces of paper!)

Now, sometimes you do want to read all the key bindings under a prefix, to find out or to refresh your memory about what’s there. In those cases I have no problem with which-key’s approach, but I find that most often I’m looking for a specific key binding and I remember a portion of the command name or maybe a bit of the binding (some Emacs key bindings are long enough that I can remember them partially but not completely!) When I’m looking for a specific binding, I really want the computer to do the searching for me, that’s what the damn thing is for!

And now I’ll tell you about the improved which-key I promised at the start. It has all the paper-like functionality of which-key, but additionally will help you search instead of patiently waiting while you to do all the work yourself. This replacement is a function called embark-prefix-help-command that comes with my Embark package. To use it simply (setq prefix-help-command #'embark-prefix-help-command). The prefix-help-command variable controls what happens when you press C-h after typing a prefix. What embark-prefix-help-command does is prompt you in the minibuffer, with completion, for a key-binding−command pair under the current prefix. You can view your options or type some input in the minibuffer to narrow the listing. It is best paired with a minibuffer completion UI that automatically displays the current completion candidates in real time as you type. (I discussed several of these in another blog post: My quest for completion.) I recommend Vertico, because it has an option to display completions in a grid, which makes embark-prefix-help-command look a lot like which-key:

(vertico-multiform-mode)
(add-to-list 'vertico-multiform-categories '(embark-keybinding grid))

Here’s what that looks like, for the same C-x C-k prefix as above:

embark-prefix-help-command-all.png

You could use this just like which-key, reading all the commands and key bindings; Vertico even lets you use C-v and M-v to page through the results (which I find slightly more comfortable than the default in which-key of C-h n and C-h p). But you can also use the minibuffer input to narrow the options. This works best if you have a completion style that lets you type a substring from anywhere inside a candidate to match it. I recommend the Orderless completion style, or I wouldn’t have written it, but the built-in substring completion style works too. Say I was trying to remember a key binding for some command that deals with keyboard macro counters ―see (info "(emacs) Keyboard Macro Counter") if you haven’t heard of these. Then you just type “cou” and get this:

embark-prefix-help-command-narrowed.png

You can also narrow by a part of the key binding rather than the command name. For example, I’m writing this blog post in org-mode and have inline images displayed, but when you add a new one that one is not displayed automatically. I could toggle the display of inline images off and on again with C-c C-x C-v, but I remembered there was a key binding for that, under the same C-c C-x prefix that involved v with some other modifiers, so I typed C-c C-x C-h and then “-v” and saw that C-M-v was the rest of the binding I was looking for.

This UI is very flexible: besides the narrowing via completion, you can do lots of other things. You can can navigate with C-n, C-p or the arrow keys among the completion candidates, press RET on a command to run it, and you have the full power of Embark: say you have embark-act bound to C-., then you can press C-. h when a candidate is displayed to show its documentation, or C-. d to go to its definition, or C-. w to copy the command name to the kill-ring. Or say you want to explore some subset of the commands more in depth, you can narrow to the subset you want and run embark-export (with C-. E) to get a nice apropos-mode buffer with a summary of those functions, like this one:

embark-prefix-help-command-apropos.png

Or say, you wanted a little table of those keyboard macro counter commands and their key bindings. Instead of embark-export you’d use embark-collect to get this buffer:

embark-prefix-help-command-collect.png

From there I copied the first two columns as a rectangle, plopped them into this org-mode buffer, added a few pipe symbols (using string-rectangle), and a header, to get this table:

Key Command
C-a kmacro-add-counter
TAB kmacro-insert-counter
C-c kmacro-set-counter
C-q > kmacro-quit-counter-greater
C-q < kmacro-quit-counter-less
C-q = kmacro-quit-counter-equal
C-r s kmacro-reg-save-counter
C-r l kmacro-reg-load-counter
C-r a > kmacro-reg-add-counter-greater
C-r a < kmacro-reg-add-counter-less
C-r a = kmacro-reg-add-counter-equal

I hope this taste of the flexibility of embark-prefix-help-command whets your appetite for more.

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 "Packages"
  "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