55

Very frequently I would need to perform the set of steps requiring multiple key strokes. For the same session those steps can be recorded in a keyboard macro.

An example is saving a frequently executed search/replace operation as a keyboard macro. But that macro is lost when I quit emacs.

How can I save my frequently used keyboard macro as a Lisp function?

For the sake of simplicity, I want to save the action of replacing "abc" with "def" as a function so that I can reuse it across emacs sessions.

Kaushal Modi
  • 25,651
  • 4
  • 80
  • 183

3 Answers3

61

Here are the steps that you can follow:

  • Select the region you want to do the search-replace.
  • Start recording macro.

    M-x start-kbd-macro

  • Do the required M-x query-replace-regexp (replace "abc" with "def") and use ! to force search-replace in the whole region.
  • Stop recording macro.

    M-x kmacro-end-or-call-macro.

  • Do M-x kmacro-name-last-macro and give the macro a descriptive name like replace-abc-with-def. You will then be able to call that macro again by doing M-x replace-abc-with-def.
  • Now save this macro as a function to a file that you load during your emacs initialization; for example, init.el.
    • M-x insert-kbd-macro
    • Select your named macro to be inserted there.

The auto-created replace-abc-with-def function definition looks like this:

(fset 'replace-abc-with-def
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([59 39 return 97 98 99 return 100 101 102 return 33] 0 "%d")) arg)))

Now you can M-x replace-abc-with-def in all your emacs sessions.

Kaushal Modi
  • 25,651
  • 4
  • 80
  • 183
  • 1
    +1 for insert-kbd-macro. That is the answer to the question (and the rest of this answer provides additional help). – Drew Sep 24 '14 at 15:31
  • 7
    Note also that Emacs can generate two different formats for keyboard macros. Which one you get when you insert-kbd-macro depends upon whether you named it using kmacro-name-last-macro (as in the above answer) or name-last-kbd-macro. – phils Oct 09 '14 at 06:06
  • 1
    Note that if you use the name-last-kbd-macro format (as mentioned by @phils above) you end up with a string, not a function. fsetting that to a symbol lets you execute the macro using M-x, but not call it from lisp (commandp -> t, functionp -> nil). Strangely, even calling it via call-interactively doesn't work (although you can use execute-kbd-macro to run it). – pyrocrasty Mar 12 '19 at 01:01
28

elmacro was already mentioned by @lunaryorn, but as the author of this package I thought it'd be nice to provide an example.

If you record a macro like this:

F3 C-e M-b M-u C-a C-n F4

Then doing M-x elmacro-show-last-macro upcase-last-word produces a buffer with:

(defun upcase-last-word ()
  "Change me!"
  (interactive)
  (move-end-of-line 1)
  (backward-word 1)
  (upcase-word 1)
  (move-beginning-of-line 1)
  (next-line 1 1))
Silex
  • 811
  • 6
  • 6
18

The elmacro package lets you view the last recorded macro as proper Emacs Lisp with M-x elmacro-show-last-macro.