Werden wir Helden für einen Tag

Home | About | Archive

Advent of emacs #2: How I make commands more discoverable in emacs

Posted on Dec 2, 2022 by Chung-hong Chan

emacs has a bad reputation for being “difficult to use”. A piece of software can’t be difficult to use for the sake of being difficult to use. Of course, many people remember emacs for forcing them to memorize a lot of key combinations (C-x C-f, C-x C-s, C-c C-r or whatnot). If how versed one in emacs is simply based on what key combinations one can memorize, that’s certainly not a very good experience. To me, memorizing key combinations actually misses the whole point. I will explain why it is —in my opinion— pointless later. This blog post is about discoverability. Let me give an example.

GUI applications are perceived to be “easy to use”. But the problem is, why on earth would one expect that in order to quit an application one should click on “File”? Why does it even make any sense? The answer isn’t it makes any sense. Instead, you click on the first item in the menu, it helps you to discover, “oh! quit is there”. GUI applications are “easy to use” because it is easier to discover their functionalities. If you use a GUI application by memorization, e.g. in order to rotate an image in GIMP, you should click on “Layer” and then “Transform” and then “Arbitrary Rotation”… It isn’t quite a good experience either.

The Linux shell also has a bad (IMO, wrong) reputation for being “difficult to use”. However, if you know how to use the “tab” key on your keyboard more efficiently, shell is a bit easier to use. That’s called tab completion. For example, you can type “le” and then press tab, the shell should tell you some suggestions. If you narrow it down to “les” and press tab, it should give you exactly “less”. And then you press space and tab again, your shell should be smart enough to list out all the files in your directory. That’s because the command less must be followed by a file name. You shell is trying to help you interactively. What does it try to help here? It tries to make your shell more discoverable. So, the shell can also be “easy to use”, only the way is different from GUI applications.

In my opinion, emacs’ bad reputation arises from its out-of-the-box poor discoverability 1. Beginners encounter a white box and have no clue how to proceed. Then they resort to the web and google for cheatsheets. Thus the whole emacs experience becomes the painful game of memorizing key combinations. 2 Semantically speaking, those default key combinations are difficult to memorize. 3 C-x C-f almost has no meaning. But what about find-file? Unless you are some super humans, you would probably think that find-file is more meaningful than C-x C-f. Similarly, split-window-right is more meaningful than C-x 3; search-backward is more meaningful than C-r.

Now, a bit of background. An emacs key combination maps to an emacs (interactive) command (“command” and “function” are used interchangeable in most cases). For example, the key combination C-x C-f maps to the command find-file by default. You can do the same thing as C-x C-f by pressing M-x find-file 4. The official terminology is key binding. By default, the key binding C-x C-f maps to the command find-file. These records are stored in keymaps.

In my experience of interacting with emacs, I use M-x increasingly more often. I believe that’s how I started to “get” emacs, rather than a horrible assemblage of key combinations. However, in a blank-state emacs pressing M-x gives you almost nothing; just an empty prompt. It is particular painful for find-file: after that emacs will ask for file path, you need to type the whole thing 5.

Completion engine

I strongly recommend having a completion engine to fix this poor discoverability problem. There are several (ivy, icomplete-mode). But this article is about how I do things. So my choice is Helm by the Helm team.

I have this in my configuration file:

(use-package helm
  :bind (("M-x" . helm-M-x)
		 ("C-x r b" . helm-filtered-bookmarks)
		 ("C-x C-f" . helm-find-files)
		 ("M-y" . helm-show-kill-ring)
		 ("C-x b" . helm-mini)
		 ("C-x r e" . helm-register))
  (helm-mode 1))

The above code snippet does three things: 1) it installs and activates helm, 2) bind several keys, 3) set helm-mode to 1, i.e. turn on helm completions for most standard emacs completions. Punkt. Let’s talk about point 2) in slightly more detail. Specifically, I override the default M-x with the command helm-M-x. And that makes M-x incredibly helpful for discovering commands.

Let’s say I really don’t know how to save what I am typing as a file. I believe the command should be somehow with “save” in it. I can just M-x and type s. helm-M-x lists out the “hits”. First from your commands history, then all other commands match your query. By the time I type “sav”, the first hit is what I want and I can just hit Return.

But if I am not so sure, I can stay in the first hit, i.e. save-buffer, hit Tab to toggle the “Action menu”. I can select “Describe function” to see the documentation of the command.

helm-find-files (in the above configuration it should be C-x C-f) and helm-mini (C-x b) also work similarly. Just type something you want to search for, helm give you some matches, select the one that watches and hit Return.

This discoverability makes emacs joyful to use.

The pointlessness of memorizing key combinations

This is the postscript. Why I think that it is pointless to memorize key combinations?

Key combinations are meant to make you more efficient. And to be more efficient, you should develop muscle memory, not to use your cognitive system to memorize key combinations. Those who play musical instruments know it better than me: You don’t play music by memorizing the G Chord is “putting my index finger on the 2nd fret of the A (5th) string, my middle finger on the 3rd fret of the low E (6th) string and my ring finger on the 3rd fret of the E (1st) string”. You play music by using the G Chord frequently enough so that you brain and muscle automatically align your fingers on the fretboard when you want to play the G Chord.

To be efficient is not to memorize key combinations, but to use those key combinations as frequently as possible. The Pareto-optimum would automatically develop the muscle memory for frequently used key combinations such as C-x C-f, C-x C-s, C-w, and C-y (I don’t want to start another controversy about C-w and C-y but not the now cultural phenonmenon of “Ctrl-x”, “Ctrl-v”). For rarely used ones, you should use M-x to discover commands instead.

Moreover, what one memorizes are the default key bindings. If you think that those default key bindings make no sense, you can always change them, the emacs equivalent of playing slack-key guitar or prepared piano. For example, one feels that save-buffer should be M-s M-s instead, put this in your configuration file.

(global-set-key (kbd "M-s M-s") 'save-buffer)

  1. Actually, vi(m) has the same problem. It is not that easy to discover how to quit vi(m) and thus the meme

  2. The menu and tool bars have been trying to help. Many functionalities are there. I don’t want to give the bad advice of turning off the menu and tool bars. Don’t do that! (oops! I did that). 

  3. I went that wrong path too and I usually try to create a story: For example, C-x C-f is about opening file. Also, it is difficult to google too. For example, it is quite difficult to google what C-x C-f does. In a latter blog post, I will talk about seeking help. 

  4. I know what you want to complain. Yes, also M-:, and then (find-file)

  5. With all due respect, emacs actually has a built-in solution called ido-mode but it is not enabled by default. For example, M-x ido-find-file is easier to use than the blank-state emacs’ find-file. For a long time, I used ido-mode

Powered by Jekyll and profdr theme, a fork of true minimal theme