Keyboard macros are a truly classic emacs feature. Still, I only started to use them years after I got sucked into emacs – not so uncommon for emacs features… There may be more people like me, so let's raise the awareness a bit.
Keyboard macros allow you to record a number of keystrokes, and replay those at some later point. This can be a great time-saver when you need to do repetitive things. In many cases, they are an easy alternative to writing some elisp to get a job done. Note, keyboard macros are should not be confused with elisp-macros, which are something else altogether.
an example
So, when would we want to use a keyboard macro? Let's take some tedious task -- for example, we have a list of a few hundred names:
Newton, Isaac Einstein, Albert Maxwell, James Turing, Alan ...
and we want to turn that into:
Isaac Newton James Maxwell Alan Turing ...
so, roughly, put the last name after the first name, and remove the comma.
We can solve this in different ways; we could simple change each line by hand. That's a fine solution if there are only a few lines, but it gets boring rather quickly.
Another way is to use regular expressions (see Building regular expressions); in this case, it's fairly easy to come up with one (assuming you know regular expressions). But let's see how we can solve it with a keyboard macro.
Schematically, we can solve this with the following:
action | key |
---|---|
go to beginning of a line | C-a |
kill (cut) the first word | M-d |
delete the next two characters | DEL DEL |
go to the end of the line | C-e |
insert a space | SPC |
yank (paste) | C-y |
go to the next line | C-n |
This may look like some magical incantation, but it comes quite natural when you are actually doing the editing.
An important thing to remember when working with keyboard macros is that you
do your commands in such a way that they can be repeated for each line. Suppose
you would select Newton
with shift-select, i.e., C-SPC
at the beginning of
the line and pressing the right arrow key 6 times – that works for Newton
,
but not for Einstein
. Instead, we need to use M-d
('kill-word
')
instead.
defining a macro
Now that we have solved the problem for a single line, let's make a keyboard macro.
We move the cursor to the first line, and start the definition by pressing
C-x (
, or alternatively, F3
. Then, we press the commands C-a
, M-d
, DEL DEL
, C-e
, SPC
, C-y
, C-n
(as in the list above). To finish the
definition, press C-x )
, (or F4
).
Hurray, we have our macro. Now, let's use it.
using the macro
Now, to execute the last defined macro, you press C-x e
. We could repeat that
for our whole list, but fortunately there's an easier way to repeat a macro n
times, using a prefix argument. For example, to repeat the macro 123 times,
you first press C-u 123
and then C-x e
.
There's a slightly shorter way to do this: instead of C-u 123
we can write
M-123
, and for C-x e
we can use F4
(kmacro=end-or-call-macro
).
You can even repeat the macro until the end of the buffer is reached with C-u 0 C-x e
; this only makes sense if the macros ever reaches the end of the buffer
of course. (Remember that you can always terminate with C-g
, keyboard-quit
)
You can also apply your keyboard macro to all lines in the selected area
(region) with M-x apply-macro-to-region-lines
(or C-x C-k r
). Important to
remember: this will actually move the cursor (point) to the start of each line,
and then execute the macro. If you want your macro like that, the
go-to-the-next-line should not be part of your macro, or you will be skipping
lines.
saving macros for later use
If you want to use multiple macros, you can name them. You can do this with
M-x name-last-kbd-macro
. If you name your macro, say, foo
(inventive as we
are), you can then execute it after that as M-x foo
, which will be available
until you exit emacs.
If you want to have the macro for future emacs sessions as well, you can use
insert-kbd-macro
, which will give you an elisp version of your macro. For our
example, this will look like:
(fset 'foo [?\C-a ?\M-d delete delete ?\C-e ? ?\C-y ?\C-n])
Not very readable, but we can put this in .emacs
, and we can use it the next
time we start emacs as well. We can also add a key binding for this, for
example:
(global-set-key (kbd "C-c f") 'foo)
This will bind foo
to C-c f
.
final notes
Keyboard macros can be useful and easy, but they are fundamentally connected
to key presses – so, if you remap your keys to something different, your
macros may not work anymore. Also, the macros are pretty much write-only in
the way we use them here. You can edit them in the macro editor though, with
M-x edit-kbd-macro M-x foo
; we'll then get something like:
;; Keyboard Macro Editor. Press C-c C-c to finish; press C-x k RET to cancel. ;; Original keys: C-a M-d 2*<delete> C-e SPC C-y C-n Command: foo Key: none Macro: C-a ;; move-beginning-of-line M-d ;; kill-word 2*<delete> ;; delete-char C-e ;; move-end-of-line SPC ;; self-insert-command C-y ;; yank C-n ;; next-line
Keyboard macros can be quite a useful trick in your arsenal. And I have not
even gone into more advanced tricks like macros with variations or the
macro ring. Please refer to the section Keyboard macros in the emacs
manual (C-h r
) for all the details.
And, finally, don't let the text-based example limit your imagination – you can turn just about any repetitive sequence of tasks into a macro.
16 comments:
You could also mention that, once a macro has been invoked via C-x e, you can repeat its invocation by pressing e repeatedly.
@danlei: thanks, added.
One thing that I didn't realise for a very long time was that you're free to jump around between buffers (C-x b, C-x o, etc.) within a macro. There's nothing restricting you to just a single buffer. I've generally tended to use this ability with one buffer supplying data to a macro to control its operation on another buffer.
For example, you could have one buffer with a list of strings that you kill one at a time with C-k, hop over to a target buffer with C-x o, isearch for it with C-s M-y, do some work at that spot, and then hop back to the control buffer with C-x o and advance to the next string for the next macro repetition with C-n.
This approach can be really powerful, and lets keyboard macros go far beyond the kinds of basic transforms that regexps could do.
You can repeat something more than 9 times using the digit-keys. If you press M-1 2 8 C-x e the macro will be repeated 128 times. You do not have to release the Meta-button, so M-1 M-2 M-8 C-x e works too.
Hmmm... the trick of pressing 'e' repeatedly doesn't work for me in emacs 21.3. Must have come in with some later version.
In the example, I would have used isearch-forward (C-s) to find the comma and used a selection to go back to the beginning of the line (C-s , RET del del C-space C-a C-w C-e space C-y).
I only mention it to help folks see different ways to define macros that need to be more flexible.
Repeated 'e' presses only seem to work if you used C-x e to invoke it the first time. Pressing F4 will should repeat the macro in either case.
@Erik: ah, didn't know that, thanks; updated.
@Bill Night,@Anonymous: indeed, F4 always works. Unless you're defining a macro while defining a macro.... Anyway, updated.
You mention how to save macros for future use. I wrote up some code which automatically makes this key string the readable version. You might want to check it out at Stack Overflow emacs keystroke representation confusion
@djcb,
Probably typo :
- start defining a keyboard macro (start-kbd-macro) with "C-x (", not "C-("
- end the definition of a keyboard macro (end-kbd-macro) with "C-x )", not "C-)".
@Bruneel Michaël: fixed, thanks!
From the beginning of the line, I would use
M-z , ;; 1. zap to the comma
M-\ ;; 2. delete-horizontal-space
C-e
M-\
spc
C-y
bkspc ;; backward-delete, whever you have it
notes:
1. M-z (zap-to-char) is very useful and will take care of names like 'van Helsing' or 'Haifin-Dache'.
2. delete-horizontal-space is useful in a number of cleanup situations (M-^ too). Twice here, just in case there is extra whitespace, make sure there's only one.
There are a number of commands that I probably only use inside of keyboard macros because they do the right thing in multiple situations.
@Todd Kaufmann: sure, the macro could be improved in various ways and indeed in real life you could make at bit more tolerant for small differences in the lines.
maybe we should have a competition for some data manipulation using the shortest possible keyboard macros, somewhat like 'perl golf' for emacs...
You could also use text to columns, using the space as to delimit and then replace the comma with nothing.
I would do it by wrapping the following in a macro and repeating it 3 times after the initial run:
(forward-word) ; M-f
(delete-char) ; C-d
(transpose-words) ; C-p (C-t for me; it's faster because I use Dvorak, not QWERTY)
(forward-char) ; C-f
--elimisteve
Hi, useful blog. please post on how to list all the saved macros.
Thanks,
Sagar
Post a Comment