September 2016

Sometimes you want to repeat an Emacs function, even when calling it originally took a few keystrokes. Here's how to make it easily repeatable. Say we have a simple function that inserts "here":

(defun insert-here ()
  (interactive)
  (insert "here"))

And bind it to C-c h h:

(global-set-key (kbd "C-c h h") #'insert-here)

This works; every time we type C-c h h, we insert "here" into the buffer. But often we want to repeat the command. Although we could use C-x z to repeat the last command, that's still two keypresses, and isn't the easiest thing to press once you've typed C-c h h. So instead, we can make a sparse keymap and in it, set "h" to this command.

(setq insert-here-keymap
      (let ((map (make-sparse-keymap)))
        (define-key map (kbd "h") #'insert-here)
        map))

Now we just need to use this keymap inside #'insert-here. We can't use #'use-local-map, because that will mean we can never insert h again: we'd always call #'use-local-map. Instead, we can use #'set-transient-map, which still uses the local keymap, but deactivates the keymap after a single key is pressed.

(defun insert-here ()
  (interactive)
  (insert "here")
  (set-transient-map
   insert-here-keymap))

Now, after activating #'insert-here, we can repeat it by pressing h. But if anything else is pressed, the keymap disables. Further presses of h will insert the letter; the keymap is no longer used. So we've accomplished our goal of easily repeating this command with a single keypress.