Emacs: Using Keyboard Macro to Record/Playback Keystrokes

, , …,

This page shows you how to use emacs keyboard macro feature, with several examples of real world use.

geek vs non geek repetitive tasks
(original bitmap drawing by Bruno Oliveira. Used with permission)

How to Record a Sequence of Keystrokes?

The keyboard macro (kmacro) feature that lets you record and playback keystrokes. The key strokes can include calling emacs commands or commands that execute any emacs lisp functions.

To record keystrokes, press 【Ctrl+x (】 (kmacro-start-macro), then start typing your keystrokes. When done, press 【Ctrl+x )】 (kmacro-end-macro). This records your keystrokes. If you made a mistake, you can cancel 【Ctrl+g】 (keyboard-quit) and start over.

To run the keystrokes you've just recorded, call call-last-kbd-macro. Here are the common kmacro commands:

Command NameKey
start-kbd-macroCtrl+x (
end-kbd-macroCtrl+x )
kmacro-end-and-call-macroCtrl+x e
call-last-kbd-macro
apply-macro-to-region-lines

Note that kmacro-end-and-call-macro is just like call-last-kbd-macro, except that if a kmacro recording is still on-going, it ends it first.

Saving Your Keyboard Macro for Future Use

If you want to use your keyboard macro for future use, you can save it. To save the macro:

  1. Call name-last-kbd-macro and give it a name.
  2. Call insert-kbd-macro. This will insert the lisp code for a named kmacro at the cursor position.
  3. Copy & Paste the code into your emacs init file.
  4. In any future emacs session, you can call your kmacro by name just like any emacs command.

Once you've saved your macro with a name, you can also give it a keyboard shortcut, such as F8.

Turn Off line-move-visual

When you record keystrokes, it is better that the arrow up/down keys move the cursor by a logical line, as opposed to visual line. (Emacs 23's default is visual line.) To set to logical line, call set-variable, then give line-move-visual, with value “nil”. (“t” for true; “nil” for false).

When you play back macro, be sure the line-move-visual is the same as when you recorded it.

Kmacro Example: Modify Atom Entries (Manipulate Text with isearch)

Here's a example of key macro use.

I have a webfeed file blog.xml in Atom Webfeed format. There are many text blocks like this:

<entry>
  <title>…</title>
  <id>…</id>
  <updated>…</updated>
  <summary>…</summary>
  <content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>see <a href="http://xahlee.blogspot.com/2011/11/emacs-lisp-exercise-insert-random-uuid.html">http://xahlee.blogspot.com/2011/11/emacs-lisp-exercise-insert-random-uuid.html</a></p>
</div>
  </content>
 <link rel="alternate" href="http://xahlee.org/emacs/blog.html"/>
</entry>

I need to remove the “content” part and simply put the URL in the alternate link, like this:

<entry>
  <title>…</title>
  <id>…</id>
  <updated>…</updated>
  <summary>…</summary>
 <link rel="alternate" href="http://xahlee.blogspot.com/2011/11/emacs-lisp-exercise-insert-random-uuid.html"/>
</entry>

Kmacro is excellent solution for this. You just call interactive search to move cursor to places you want, and do delete or copy & paste. Like this.

  1. isearch-forwardCtrl+s】 for http://xahlee.blogspot.
  2. isearch-backwardCtrl+r】 for ", move cursor forward 1 position, set mark.
  3. isearch-forward for ", do a copy. Now the blog URL is in clipboard
  4. isearch-backward for <content , set mark.
  5. isearch-forward for </content>.
  6. Press delete to delete the content section.
  7. isearch-forward for href=.
  8. Do steps to delete the URL (using isearch and set mark like above), then paste the new one.

Once i recorded these steps, then i call kmacro-end-and-call-macroCtrl+x e】. This way, every 2 keystrokes makes one entry change. This allows me to visually verify what i've done is correct. I could also press 【Ctrl+u】, then a number, then 【Ctrl+x e】 to repeat it automatically n times.

Kmacro Example: Add Title of URL (Open File, Get Parts of Text, Paste)

Here's a example of keyboard macro use. I use macro about few times a month. When you need it, it is extremely convenient.

Today, i have about 60 lines, each line is a URL, like this:

http://xahlee.org/3d/3D_inputs.html

I need it to be like this:

• 〈Mathematical Models of 3D Inputs Control〉
http://xahlee.org/3d/3D_inputs.html

Where the first line is the title of that page.

Here are some of my lines:

http://xahlee.org/Periodic_dosage_dir/Logitech_G13_Gameboard.html
http://xahlee.org/Periodic_dosage_dir/bangu/pinyin_frequency.html
http://xahlee.org/Periodic_dosage_dir/logitech_trackball.html
http://xahlee.org/Periodic_dosage_dir/mouses.html
http://xahlee.org/Periodic_dosage_dir/trackball.html
…

Here's what i do to record this as keyboard macro.

  1. First, replace all http://xahlee.org/ by a web root ~/web/xahlee_org/ 〔☛ Emacs: Find/Replace Tutorial
  2. Move cursor to the first line.
  3. Start kmacro.
  4. Alt+xffap (find-file-at-point) to open the file.
  5. Move cursor to top. 【Ctrl+↖ Home
  6. Grab the HTML title between <title>…</title> tag, by using isearch-forward for <title>, set-mark, then search for <, move cursor 1 position back, then copy it.
  7. Close the file.
  8. Type [], move cursor in, paste the title. (you can later use query-replace to replace the […] by • 〈…〉. (or you can insert the bullet and angle brackets directly. 〔☛ Emacs & Unicode Tips〕)
  9. Move cursor 2 position down to the next line.
  10. End the kmacro.

Now, each time you call call-last-kbd-macro, a line will be processed, with its title inserted above the line.

You can also select all lines that has not yet been processed, then call apply-macro-to-region-lines. Then, in about 1 second, all 60 lines become this:

• 〈Logitech G13 Advanced Gameboard Review〉
http://xahlee.org/Periodic_dosage_dir/Logitech_G13_Gameboard.html

• 〈Chinese Pinyin Letter Frequency and Dvorak Layout〉
http://xahlee.org/Periodic_dosage_dir/bangu/pinyin_frequency.html

• 〈Logitech Trackball Mouse Reviews〉
http://xahlee.org/Periodic_dosage_dir/logitech_trackball.html

• 〈Review Of Microsoft SideWinder Gaming Mouses〉
http://xahlee.org/Periodic_dosage_dir/mouses.html

• 〈Trackball Mouse Reviews〉
http://xahlee.org/Periodic_dosage_dir/trackball.html

…

In keyboard macro, you can call any emacs command, or even more than one command. Emacs's kmacro feature simply play back the keystrokes.

keymacro is extremely useful whenever you need to do something repeatitive. It is a great time-saver. You do not need to know elisp to use it. Even if you are a elisp expert, many repeative tasks are still best done with a kmacro. With kmacro, i can finish this job in 30 seconds. But if i were to write a elisp for it, it easly can take 20 min and drains a lot brain juice.

Kmacro Example: Repeatedly Eval a Emacs Lisp Expression

Here's another example of kmacro use.

I have a function insert-random-uuid 〔☛ Emacs Lisp Exercise: insert-random-uuid〕 I want to call it hundreds of times to see its output. Let's just say i want to call the elisp expression (random 100) one hundred times.

One way is to write a elisp command on the spot, like this:

(defun xx-random-test ()
  "test"
  (interactive)
  (dotimes (ii 100) (insert (format "%d " (random 100))))
  )

But that takes 5 minutes to write, plus you need to have elisp knowledge. You can use a kmacro to do this fast, with the following steps.

More Kmacro Examples

For more example of kmacro use, see:

blog comments powered by Disqus