Xah Lee, 2010-11-16
This page shows you how to use emacs keyboard macro feature, and a example of real world use.
Emacs has a keyboard macro (kmacro) feature that lets you record and playback keystrokes. I learned the basics since i started to use emacs in 1998, but actually never used it much, maybe few times a year. Since 2007, i learned the command “apply-macro-to-region-lines”, which made it more useful. Still, i use kmacro perhaps twice a month. However, when i use it, it typically reduces the time to do a task by some 10 fold. So, a 10 minutes job becomes 1 minute, a hour job of repeatitive manual text manipulation becomes 5 minutes.
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】 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 Name | Key |
|---|---|
| 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 | ◇ |
If you want to use your keyboard macro (kmacro) for future use, you can save it. To save the macro:
Once you've saved your macro, you can also give it a keyboard shortcut, such as F8.
When you record keystrokes, it is better that the arrow up/down keys move the cursor thru 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.
Here's a example of how i use keyboard macro. Usually, i use macro about few times a month. When you need it, it is extremely time saving. Otherwise you might spend hours doing it, even if you know elisp well.
Today, i have about 60 lines, each line is a url, like this:
http://xahlee.info/3d/3D_inputs.html
I need it to be like this:
• 〈Mathematical Models of 3D Inputs Control〉 http://xahlee.info/3d/3D_inputs.html
Where the first line is the title of that page.
Here are some of my lines:
http://xahlee.info/PageTwo_dir/Personal_dir/dvorakKeymap.txt http://xahlee.info/Periodic_dosage_dir/Logitech_G13_Gameboard.html http://xahlee.info/Periodic_dosage_dir/bangu/pinyin_frequency.html http://xahlee.info/Periodic_dosage_dir/logitech_trackball.html http://xahlee.info/Periodic_dosage_dir/mouses.html http://xahlee.info/Periodic_dosage_dir/trackball.html …
I've written a elisp code that turns a url on my site into the format i want. Here's the lisp code:
(defun xah-cite () "Change the file path under cursor into title and URL. For example, this line /Users/xah/web/xahlee_org/emacs/emacs.html becomes • 〈Xah's Emacs Tutorial〉 http://xahlee.info/emacs/emacs.html The title came from HTML file's title tag. File path must be a url scheme, full path, or relative path. Example url schemes among browsers and OSes: C:\\Users\\xah\\web\\xahlee_org\\emacs\\emacs.html ; IE file:///C:/Users/xah/web/xahlee_org/emacs/emacs.html ; Windows: firefox, chrome, safari file://localhost/C:/Users/xah/web/xahlee_org/emacs/emacs.html ; Windows opera file:///Users/xah/web/xahlee_org/emacs/emacs.html ; osx: safari, firefox file://localhost/Users/xah/web/xahlee_org/emacs/emacs.html ; opera Example path variations: c:/Users/xah/web/xahlee_org/emacs/emacs.html /Users/xah/web/xahlee_org/emacs/emacs.html ~/web/xahlee_org/emacs/emacs.html emacs.html ; relative path This is Xah Lee's personal command assuming a particular dir structure." (interactive) (let (bds ff title) (setq bds (bounds-of-thing-at-point 'filename)) (setq ff (buffer-substring-no-properties (car bds) (cdr bds))) ;; change file path to full path (setq ff (replace-regexp-in-string "^http://www\\." "http://" ff)) (setq ff (replace-regexp-in-string "/$" "/index.html" ff)) (setq ff (cond ((string-equal system-type "windows-nt") ; Windows (replace-regexp-in-string "^http://xahlee\\.org/" "c:/Users/xah/web/xahlee_org/" ff) ) ((string-equal system-type "darwin") ; Mac (replace-regexp-in-string "^http://xahlee\\.org/" "/Users/xah/web/xahlee_org/" ff) ) ) ) (setq ff (local-url-to-file-path ff)) (setq ff (expand-file-name ff )) (setq title (if (string-match ".+html\\'" ff) (get-html-file-title ff) (file-name-nondirectory ff))) (delete-region (car bds) (cdr bds)) (insert "• 〈" title "〉\n" (xah-web-path-to-url ff)) ))
I have defined a alias for this command to save me typing, because i use it often. Alias is defined like this:
(defalias 'c 'xah-cite)
So, to change each url to the format i want, first i move cursor to the line, then type 【Alt+x c Enter】 (Actually i type “Alt+a” instead of “Alt+x”, because i'm using ErgoEmacs Keybinding. Actually, i just type the Caps Lock key because i'm using a AutoHotkey script. See: System-wide ErgoEmacs Keybinding for Windows, Mac, Bash.). But now i need to do this 60 times because i have 60 lines! So, a keyboard macro comes to use. Here's how i do it.
Then, i 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:
• 〈dvorakKeymap.txt〉 http://xahlee.info/PageTwo_dir/Personal_dir/dvorakKeymap.txt • 〈Logitech G13 Advanced Gameboard (Review)〉 http://xahlee.info/Periodic_dosage_dir/Logitech_G13_Gameboard.html • 〈Chinese Pinyin Letter Frequency and Dvorak Layout〉 http://xahlee.info/Periodic_dosage_dir/bangu/pinyin_frequency.html • 〈Logitech Trackball Mouse Reviews〉 http://xahlee.info/Periodic_dosage_dir/logitech_trackball.html • 〈Review Of Microsoft SideWinder Gaming Mouses〉 http://xahlee.info/Periodic_dosage_dir/mouses.html • 〈Trackball Mouse Reviews〉 http://xahlee.info/Periodic_dosage_dir/trackball.html …
Emacs is fantastic!
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 and the steps are the same. It is a great time-saver. You do not need to know elisp to use it. Even if you are a elisp master, 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.
For another example of keyboard macro use, see: Emacs Keyboard Macro Example: Adding HTML Attribute.