Command Discovery In Emacs

One thing that has annoyed me forever about Emacs is that when you define a command for a specific more, the commands become so… global.

I mean, you define a command in, say, eww-mode for navigating to the next link, and that command only works in that mode. But then you type `M-x ewwTAB’ to try to remember what the command to open an HTML file in eww is, and Emacs will spit back at you:

The vast majority of those commands make sense within eww only, and not in the *scratch* buffer where I was.

So now I’ve introduced markup for commands in Emacs that specify what modes they’re meant to be used it. So if you now type `M-x ewwTAB’ in *scratch*, Emacs will give you a distinctly shorter list:

Right! The command I was searching for was `M-x eww-open-file’.

It’ll take a long while until all commands in Emacs are tagged properly… but if you wanna start helping, please do! It’s not complicated, but it does require some thought, because commands that really should be global are commonly mixed in with mode-specific commands. Marking up eww.el took me about five minutes, and that’s a file with four different modes.

The basic idea is that commands, today, are defined as such:

(defun foo-thing (arg)
  (interactive "p")

The `interactive’ thing says “this is a command”. This just needs to be annotated as to what mode it’s for:

(defun foo-thing (arg)
  (interactive "p" foo-mode)

Simple! Now Emacs will know that `foo-thing’ is a command that’s only applicable for `foo-mode’ (or any modes that is derived from `foo-mode’).

The `foo-mode’ thing can also be a list of modes if the command applies to several modes, but that’s actually kinda rare.

To get started with Emacs development, have a peek at this blog post. Building Emacs is fun and easy.

Start fixing up modes, send in patches, and watch how `M-x TAB’ gets more and more usable!

6 thoughts on “Command Discovery In Emacs”

  1. I feel like this change should not require changes to existing definitions.

    It should also not be the default command bound to `M-x`.

    So you could have an `execute-extended-command-in-mode` function that a user may choose to use.

    And you could have a (associate ‘foo-thing ‘foo-mode) form or something more sugary to link commands to modes.

    If you want the association to be made in your own definition, you can create a define-foo-mode-command macro to do that.

  2. The change being missing in existing definitions won’t impact them in a negative way, it will only mean M-x will include that function as it does now.

    I would argue there should be a new command that disregards this “mode annotation” and shows everything, but really if you are interested in a function for other modes than the current one you are either writing elisp or exploring some functionality, you are way more likely to get there via C-h f “describe-function” rather than than “execute-extended-command”.

  3. Looks like a great start to contribute to emacs.
    Is there any list – which files in emacs src should be update to that convention?
    I’ve started with /lisp/play ‘grep -L “(interactive nil” *’ but all files in this dir are already have been updated.

    1. No, there’s no list — they should basically all be updated (except the ones that are also distributed via ELPA and should work in earlier Emacs versions).

Leave a Reply