2010-11-16

Emacs Keyboard Macro and Examples

Perm url with updates: http://xahlee.org/emacs/emacs_macro_example.html

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

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, press 【Ctrl+x e】 (“kmacro-end-and-call-macro”) or call “call-last-kbd-macro” or “apply-macro-to-region-lines”.

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

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:

  • ① Call “name-last-kbd-macro” and give it a name.
  • ② Call “insert-kbd-macro”. This will insert the kmacro lisp code at the cursor position.
  • ③ Copy and Paste the code into your emacs init file.
  • ④ In any future emacs session, you can call your kmacro by name (with 【Alt+x ‹yourMacroName›】).

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: Add Title of URL

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/ (See: Find & Replace with Emacs.)
  2. Move cursor to the first line.
  3. Start kmacro.
  4. Use “ffap” (“find-file-at-point”) to open the file.
  5. Move cursor to top.
  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. (See: Emacs and 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 at the top.

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.

In general, kmacro 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 repeatives jobs 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.

Example: Modify Atom Entries

Here's another example of kmacro use.

I have a webfeed file 〔blog.xml〕 in Atom Webfeed format. There are many entries 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>

So, kmacro is excellent solution, with these steps.

  1. “isearch-forward” for http://xahlee.blogspot.
  2. “isearch-backward” 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 and paste the new one.

Once i recorded these steps, then i press 【Alt+x】, then 【 Enter】 to execute “call-last-kbd-macro”. This way, every 3 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 “call-last-kbd-macro” to repeat it automatically n times.

For another example of keyboard macro use, see: Emacs Keyboard Macro Example: Adding HTML Attribute.