41

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.

48

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.

  • 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
  • 5
    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 9 '14 at 6:06
  • 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 at 1:01
24

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))
17

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

  • 7
    Someone recommending my package \o/ – Silex Oct 8 '14 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.