417 lines
18 KiB
HTML
417 lines
18 KiB
HTML
<!--startcut BEGIN header ==============================================-->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>Emacs Macros and the Power-Macros Package LG #47</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!--endcut ============================================================-->
|
|
|
|
<H4>
|
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
|
</H4>
|
|
|
|
<P> <HR> <P>
|
|
<!--===================================================================-->
|
|
|
|
<center>
|
|
<H1><font color="maroon">Emacs Macros and the Power-Macros Package</font></H1>
|
|
<H4>By <a href="mailto:blackie@ifad.dk">Jesper Kjær Pedersen</a></H4>
|
|
</center>
|
|
<P> <HR> <P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
|
|
<h2>Abstract</h2>
|
|
People sometimes tend to forget that computers are a tool that can make
|
|
their life much easier. One of the things computers are especially good at,
|
|
and which is easy for you to teach, is monotonic repetitive work. It gets
|
|
even better: This kind of work also seems to be the work humans are worst at
|
|
doing that is, monotonic repetitive work tends to be very error-prone.<p>
|
|
|
|
Emacs can eliminate the repetitive work with a very useful concept
|
|
called macros. Macros are basically keystrokes that Emacs types for
|
|
you.<p>
|
|
|
|
This article will teach you about Emacs macros and show you a number of
|
|
useful examples. Furthermore, it will teach you about an Emacs
|
|
package I written called power-macros, which makes it very easy to bind macros to
|
|
keys and to save them to a file for use in later Emacs sessions.<p>
|
|
|
|
<h2>Defining an Emacs macro.</h2>
|
|
Defining an Emacs macro is done by pressing <tt>C-x (</tt> (That is press
|
|
Ctrl, hold it down and press x, and then release Ctrl and x and press the
|
|
opening bracket). The subsequent keystrokes will be part of your
|
|
macro that is whenever you ask Emacs to execute your macro, these
|
|
keystrokes will <i>be typed for you</i>. When you are done defining the
|
|
macro, press <tt>C-x )</tt><p>
|
|
|
|
When a macro has been defined you may ask Emacs to imitate your
|
|
keystrokes as often as you want simply by pressing <tt>C-x e</tt>.<p>
|
|
|
|
<h3>Two-cent tip</h3>
|
|
If you need to repeat macros several times, then it might be quite annoying
|
|
that you need to press two keys to execute the macro defined. (That is, if
|
|
you need to execute the macro three times, then you must press C-x e, C-x e,
|
|
C-x e). A solution to this may be to bind <i>execute last defined keyboard
|
|
macro</i> to a single key press. This way, you may for example bind it to
|
|
shift-F1, by inserting the following code into your <tt>.emacs</tt>
|
|
file:
|
|
<pre>
|
|
(global-set-key [(shift f1)] 'call-last-kbd-macro)
|
|
</pre>
|
|
|
|
<h2>Example: Making the current word bold</h2>
|
|
That's it now you have learned the basics about Emacs macros, but
|
|
I'm pretty sure that you haven't had the feeling yet that this would change
|
|
your world much, right? To be honest, I've used Emacs for more than seven
|
|
years, but until less than a year ago, I didn't see the light either...
|
|
Therefore, here comes a small example to vet your appetite. More will
|
|
follow later in the article.<p>
|
|
|
|
Imagine that you often want to make the current word in boldface (in
|
|
HTML documents), you could simply do that by inserting <tt><b></tt>
|
|
and <tt></b></tt> around the word. That's no big job, but if you are
|
|
copy-editing a book, where you need to make words in boldface hundreds
|
|
of times each hour, then a macro, that can do this may really spare you a
|
|
lot of time.<p>
|
|
|
|
The macro is easily recorded: Go to the beginning of the word, insert
|
|
<tt><b></tt>, go to the end of the word, insert <tt></b></tt>,
|
|
and there you are!<p>
|
|
|
|
Ohhh, not so fast! There is one very important point to notice about this
|
|
you are not allowed to go to the beginning respectively the end of the word
|
|
by pressing the arrow key a number of times! Why not? Well if you do, then
|
|
the macro will fail to find the border of the word if your word is of a
|
|
different length than the word used when defining the macro. You must
|
|
therefore instead use the commands <tt>forward-word</tt> and
|
|
<tt>backward-word</tt>. These commands are bound to control and the arrow
|
|
keys. Thus to go to the beginning of a word, simply press control and the
|
|
left arrow key.<p>
|
|
|
|
Basically there exist two kinds of macros: those that are used now and again,
|
|
and those that are used a number of times in a row and then never used
|
|
again. The above is an example of a macro of the first kind. The
|
|
description of the second kind is out of the scope for this article, but an
|
|
example could be a macro, that added <tt>/* REMOVE:</tt> to the beginning
|
|
of a line, and <tt>*/</tt> to the end of a line. You may use such a macro a
|
|
number of times in a row, to comment out a whole function in C for later removal.<p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h2>Making macros more general</h2>
|
|
In some C++ programs you will often find constructs which resemble the
|
|
following:
|
|
<pre>
|
|
for (bool cont=iterator.First(value); cont; cont=iterator.Next(value)) {
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
The only difference from occasion to occasion is the names <i>cont</i>,
|
|
<i>iterator</i>, <i>value</i>, and of course the content in between the
|
|
curly brackets.<p>
|
|
|
|
If you insert the code above often, then you may wish to build a macro,
|
|
which will help you with this. Your first attempt may be to define a macro,
|
|
which simply inserts:
|
|
<pre>
|
|
for (bool =.First(); ; =.Next()) {
|
|
}
|
|
</pre>
|
|
|
|
That is, a macro that simply leaves out all the parts that may change from
|
|
time to time. This is, however, not as useful as it could be, simply
|
|
because you would need to type <i>cont</i> three times, and <i>iterator</i>
|
|
and <i>value</i> each two times. What you really would need was for Emacs
|
|
to ask you about the names to use instead of <i>cont</i>,<i>iterator</i>,
|
|
and <i>value</i>.<p>
|
|
|
|
Guess what? you can do that with macros! The trick is called <tt>recursive
|
|
editing</tt>. With recursive editing you tell Emacs to stop at a specific
|
|
place in the macro, you do some editing, and when you are done
|
|
you tell Emacs to continue with the macro. <p>
|
|
|
|
When you record the macro, you may tell Emacs to enter recursive editing by
|
|
pressing <tt>C-u C-x q</tt>. Then whenever you execute the macro
|
|
Emacs will stop macro execution at that point and let you do some editing,
|
|
and the macro will first continue when you press C-M-c (That is
|
|
control-meta-c, if there is no meta key on your keyboard it is most likely
|
|
the alt key instead.).<p>
|
|
|
|
While you record the macro, Emacs will also enter recursive editing at that
|
|
point. That is, the editing you do from the point you press <tt>C-u C-x
|
|
q</tt> and till you press <tt>C-M-c</tt> will <b>not</b> be part of the macro.<p>
|
|
|
|
Ok, we are almost ready to develop a very neat and useful macro, but first
|
|
lets exercise what we've learned above with a simple example. Type the following:
|
|
<pre>
|
|
C-x ( Type a word ==> C-u C-x q
|
|
</pre>
|
|
|
|
Now type <i>Hello World</i>, and when done, continue typing the following:
|
|
<pre>
|
|
C-M-c <== C-x )
|
|
</pre>
|
|
|
|
The above inserted the following text into your buffer: <tt>Type a word
|
|
==>Hello World<==</tt>. Furthermore it also defined a macro, which
|
|
inserts this text except for the words <tt>Hello World</tt>. Whenever you
|
|
execute the just defined macro Emacs will pause after having inserted
|
|
<tt>Type a word ==></tt>, and when you press <tt>C-M-c</tt>, it will
|
|
continue with the macro, which means that it will insert the text <tt><==</tt>.<p>
|
|
|
|
Can you see where we are heading? Now we have the tools to ask the user for
|
|
the three names needed, so all we need now is a way to fetch the
|
|
information he typed and insert it at the appropriate places.<p>
|
|
|
|
Fetching the information could be done in several ways. The simplest way
|
|
(that is the one, which requires the smallest knowledge about Emacs) would
|
|
simply be to switch to a temporary buffer, let the user type in the
|
|
information there, and whenever one of the words are needed, simply go to
|
|
this buffer, and fetch it there.<p>
|
|
|
|
A much smarter way is to use <i>registers</i>. A register is a
|
|
container where you may save the text of the current region for later
|
|
use. To insert text into a register, mark a region, and press
|
|
<tt>C-x r s</tt> and a letter (the letter indicates which of the registers
|
|
to save the information to) Later you may insert the content of the
|
|
register into the buffer by pressing <tt>C-x r i</tt> and pressing
|
|
the letter you typed above.<p>
|
|
|
|
Now that's it. Below you can see all the keystrokes needed to record this
|
|
macro. Text in between quotes should be typed literally, and text in italic
|
|
are comments, which you should not type.<p>
|
|
|
|
It may seem like much to type to obtain this, but on the other hand,
|
|
when you are done, you will have a very user friendly interface to
|
|
inserting the given for-loops.
|
|
|
|
<blockquote>
|
|
"Bool: " C-space <i>This will set the mark - that is one end of the region</i><br>
|
|
C-u C-x q <i>Type the name of the first bool here</i><br>
|
|
C-x C-x <i>This will make the region active</i><br>
|
|
C-x r s a <i>Copy the just typed word to the register named a</i><br>
|
|
C-a C-k <i>Delete the line, as the just inserted text should not be part of the buffer</i><br>
|
|
"Iterator: " <i>Now continue as above, and save to register b</i><br>
|
|
"Value: " <i>Once again continue and this time save to register c</i><br>
|
|
"for (bool " <i>Now we've started to actually type the for-loop</i><br>
|
|
C-x r i a <i>Insert the name of the boolean</i><br>
|
|
"= " C-x r i b <i>Insert the name of the iterator</i><br>
|
|
C-e ".First(" C-x r i c <i>The name of the value</i><br>
|
|
C-e "); " C-x r i a C-e "; " C-x r i a C-e " = " C-x r i b C-e ".Next(" C-x
|
|
r i c C-e ")) {" Return "}"
|
|
</blockquote>
|
|
|
|
|
|
|
|
<h1>Power Macros</h1>
|
|
Power Macros is an Emacs package, which I developed out of frustration of
|
|
not being able to define a macro, bind it to a key, and have it bound there
|
|
for future Emacs sessions. (Or rather, not being able to do so very easy).<p>
|
|
|
|
To use this Emacs package, download the file from its <a
|
|
href="http://www.imada.sdu.dk/~blackie/emacs/">home page</a>. Copy the lisp
|
|
file to somewhere in your load path, and insert the following into your
|
|
<tt>.emacs</tt>file:
|
|
<pre>
|
|
(require 'power-macros)
|
|
(power-macros-mode)
|
|
(pm-load)
|
|
</pre>
|
|
|
|
If you do not know what a load path is, or do not have one, then create a
|
|
directory called <tt>Emacs</tt>in your home directory, copy the file to
|
|
this directory, and insert the following line into your <tt>.emacs</tt>
|
|
file before the lines above:
|
|
<pre>
|
|
(setq load-path (cons "~/Emacs" load-path))
|
|
</pre>
|
|
|
|
When that is done, you may simply press <tt>C-c n</tt>, when you have
|
|
defined a macro, and Emacs will ask you the following questions in the
|
|
mini-buffer:
|
|
|
|
<dl>
|
|
<dt>Which key to bind the macro to.
|
|
<dd>First Emacs must know which key the macro should be bound to. When you
|
|
are done answering these questions, then the macro will be available simply
|
|
by pressing this key, and you may that way have several macros defined at
|
|
the same time.<p>
|
|
|
|
|
|
<dt>How should the macro be accessible.
|
|
<dd>With power macros you may make the macro accessible in one of two ways:
|
|
1) Global - that is it is accessible in every buffer. 2) As a major mode
|
|
specific macro - that is the macro is only accessible in buffers with a
|
|
given major mode.<p>
|
|
|
|
As an example of a mode specific macro, think about the
|
|
<i>for-loop</i>-macro from the example above. This macro is only useful
|
|
when writing C++ programs. Furthermore you may need a similar macro for
|
|
programming Java (which of course use Java syntax rather than C++
|
|
syntax). With power-macros you may bind both the macro for C++-mode and the
|
|
macro for Java-mode to the same key (say <tt>C-M-f</tt>), and then the
|
|
correct one will be used in the given mode.<p>
|
|
|
|
<dt>Which file should it be saved to.
|
|
<dd>By default Emacs saves the macros defined with power-macro to the file
|
|
named <tt>~/.power-macros</tt>. If that is Ok for the macro you are
|
|
defining, then simply press enter at this question. If you do not want to
|
|
save the given macro to a file for future Emacs sessions, then remove the
|
|
suggested text (so that you answer the question with an empty
|
|
string). Finally you may of course name another file. In the <a
|
|
href="#local_file">section below</a>, there is a description of when this
|
|
can be of special interest.<p>
|
|
|
|
<dt>What is its description.
|
|
<dd>Finally you have to write a description for the macro just
|
|
defined. This will make it much easier for you to identify it later, when
|
|
you have forgot which key you have bound it to, or when you are searching
|
|
for a key to bind a new macro to.
|
|
</dl>
|
|
|
|
As part of binding the macro to a key, Emacs will also check if the given
|
|
binding will override an existing binding. If this is the case it will warn
|
|
you about this, and ask you for confirmation to continue the definition.
|
|
|
|
|
|
|
|
|
|
<h2><a name="local_file">Local Macros</a></h2>
|
|
For some time ago I was going to give a speech on Emacs. I have done that a
|
|
number of times before, so I haven't done any special preparation for this
|
|
specific speech. When I was driving to the speech (by train) I decided
|
|
shortly to go through my presentation anyway. I was terrified to see that the
|
|
presentation program suddenly didn't work on my machine.<p>
|
|
|
|
So there I was, less than an hour to my speech and my presentation program
|
|
didn't work! What should I do?! The answer was kind of obvious, why not
|
|
make the presentation using Emacs?! Fortunately the input to the other
|
|
presentation program was ASCII, and the only construct I used in the
|
|
presentation was enumerated lists, so it was very easy to rewrite the
|
|
presentation so it looked good in an Emacs buffer (with a slightly enlarged
|
|
font). Now there was only one problem: How could I easily go
|
|
forward/backward one presentation page?<p>
|
|
|
|
Can you guess what the answer was? Yes you are right, the answer was to
|
|
create two macros. One going forward one page, and another going backward
|
|
one page.<p>
|
|
|
|
Going forward one page was done the following way:
|
|
<ol>
|
|
<li>Search for a line starting with a number of equal signs. This was
|
|
namely the second line of each presentation page (Just below the title of
|
|
the page).
|
|
<li>Press <tt>C-1 C-l</tt> (that is control-one control-el) This would
|
|
locate this line as the second line of the screen. And consequently the title
|
|
of the page would thus be the first one.
|
|
<li>Go to the beginning of the next line. This was necessary so the
|
|
subsequent search would not find the current page.
|
|
</ol>
|
|
|
|
The two macros, just defined, is only useful for the given file (and later
|
|
to all the files, which contains a presentation made for viewing with
|
|
Emacs). Therefore it would be a bit annoying to have these macros defined
|
|
and bound to keys all the times, especially given that there might be
|
|
several month before my next Emacs presentation.<p>
|
|
|
|
The two macros should therefore be saved to a separate file, and
|
|
whenever needed I could simply load them. Loading a power macro is done by
|
|
using the function <tt>pm-load</tt>. Thus I could load the macros by
|
|
pressing <tt>M-x</tt> typing pm-load, pressing enter, and typing the name
|
|
of the file to load.
|
|
|
|
Loading the macros for the presentation could be done even more automatic,
|
|
by inserting the following lines as the very last lines of the file:
|
|
|
|
<pre>
|
|
Local Variables:
|
|
eval: (pm-load "presentation.macro")
|
|
End:
|
|
</pre>
|
|
|
|
In the above it is assumed that the name of the file containing the macros
|
|
is called <tt>presentation.macro</tt>.<p>
|
|
|
|
Now Emacs automatically loads the presentation macros whenever the file is opened.
|
|
|
|
<h2>Managing Power Macros</h2>
|
|
When you have defined a number of macros, you might want to do various
|
|
managing functions on your macros. This is done by pressing <tt>C-c
|
|
m</tt>. This will bring up a buffer as the one you can see below:<p>
|
|
|
|
<img src="gx/pedersen/manage.jpg" BORDER=1>
|
|
<BR CLEAR=all>
|
|
|
|
What you see in this buffer is your power macros, each separated with a
|
|
line of dashes. Many of the keys have special meaning in this buffer (Just
|
|
like the keys have special meaning in the buffer managing buffer or in the
|
|
dired buffer).<p>
|
|
|
|
By pressing the enter key on top of one of the fields lets you edit the
|
|
given field. Editing a field does in fact mean either to change its
|
|
content, or to copy the macro to a new one with the given field changed. You specify
|
|
whichever of these meanings you intend, when you have pressed enter on the
|
|
field.<p>
|
|
|
|
Deletion of macros is done in two steps, first you mark the macros which
|
|
you want to delete, and next you tell Emacs to actual delete them. If you
|
|
know either the buffer managing buffer or dired-mode, then you will be
|
|
familiar with this two step process.
|
|
|
|
<h1>The End</h1>
|
|
If your appetite has been vet to learn more about Emacs, then I can inform
|
|
you that I'm the author of a book
|
|
on Emacs called "Sams Teach Yourself Emacs in 24 Hours". (ISBN:
|
|
0-672-31594-7). To learn more about this book, please visit it's home page
|
|
on the URL <a
|
|
href="http://www.imada.sdu.dk/~blackie/emacs/">http://www.imada.sdu.dk/~blackie/emacs/</a>.
|
|
This is also the page you should visit if you want to download the
|
|
power-macro package.<p>
|
|
|
|
|
|
<address><a href="http://www.imada.sdu.dk/~blackie/">Jesper Kjær
|
|
Pedersen</a> <<a href="mailto:blackie@ifad.dk">blackie@ifad.dk</a>></address>
|
|
|
|
|
|
|
|
|
|
<!-- BEGIN copyright ==================================================-->
|
|
<P> <hr> <P>
|
|
<H5 ALIGN=center>
|
|
|
|
Copyright © 1999, Jesper Kjær Pedersen<BR>
|
|
Published in Issue 47 of <i>Linux Gazette</i>, November 1999</H5>
|
|
<!-- END copyright ===================================================-->
|
|
|
|
|
|
|
|
|
|
|
|
<!--startcut footer ===================================================-->
|
|
<P> <hr> <P>
|
|
<A HREF="index.html"><IMG ALIGN=BOTTOM SRC="../gx/indexnew.gif"
|
|
ALT="[ TABLE OF CONTENTS ]"></A>
|
|
<A HREF="../index.html"><IMG ALIGN=BOTTOM SRC="../gx/homenew.gif"
|
|
ALT="[ FRONT PAGE ]"></A>
|
|
<A HREF="nielsen.html"><IMG SRC="../gx/back2.gif"
|
|
ALT=" Back "></A>
|
|
<A HREF="../faq/index.html"
|
|
><IMG SRC="./../gx/dennis/faq.gif"
|
|
ALT="[ Linux Gazette FAQ ]"></A>
|
|
<A HREF="pollman.html"><IMG SRC="../gx/fwd.gif" ALT=" Next "></A>
|
|
<P> <hr> <P>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|