Emacs Macros and the Power-Macros Package

by Jesper Pedersen

People sometimes tend to forget that computers are tools that can make their lives much easier. One of the things computers are especially good at, and which is easy to teach them is monotonous, repetitive work. It gets even better. This kind of work also seems to be the work humans are worst at doing; that is, monotonous, repetitive work tends to be very error-prone. Emacs can eliminate repetitive work with a very useful concept called macros. Macros are basically keystrokes that Emacs types for you.

This article will describe Emacs macros and show you a number of useful examples. Furthermore, it will discuss an Emacs package I have written called power-macros, which makes it very easy to bind macros to keys and save them to a file for use in later Emacs sessions.

Defining an Emacs Macro

Defining an Emacs macro is done by pressing CTRL-x (. That is, press CTRL, hold it down and press x, release both, then press the open parenthesis. The subsequent keystrokes will be part of your macro; that is, when you ask Emacs to execute your macro, these keystrokes will be typed for you. When you are done defining the macro, press CTRL-x ).

When a macro has been defined, you can ask Emacs to imitate your keystrokes as often as you want simply by pressing CTRL-x e.

Two Cent Tip

If you need to repeat a macro several times, it might be quite annoying to have to press two keys to execute it. A solution to this is to bind a command to “execute-last-defined-keyboard macro” to a single key press. For example, you could bind this command to SHIFT-F1 by inserting the following code into your .emacs file:

(global-set-key [(shift f1)] 'call-last-kbd-macro)
Example: Making the Current Word Bold

Those are the macro basics. I'm fairly sure you don't yet have the feeling this would change your world much, right? Therefore, here is a small example to whet your appetite. More will follow later.

Imagine that you often want to make the current word in boldface. In HTML documents, you could do that simply by inserting <b> and </b> around the word. That's no big job, but if you are copy-editing a book and need to make words in boldface hundreds of times each hour, a macro to do this can save you a lot of time.

The macro is easily recorded: press CTRL-x (, go to the beginning of the word, type <b>, go to the end of the word, type </b>, CTRL-x ), then press CTRL-x e at the beginning of each word you wish to bold in the document.

There is one very important point to notice about this: you are not allowed to go to the beginning or end of the word by pressing the arrow key a number of times! Why not? Well, if you do, 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 instead use the commands forward-word and backward-word. These commands are bound to CTRL and the arrow keys. Thus, to go to the end of a word, simply press CTRL and the right-arrow key.

Basically, there are two kinds of macros: those used infrequently, and those used many times in a row and then never used again. The “make word bold” example is a macro of the first kind. The description of the second kind is outside the scope of this article, but one example could be a macro that added /* REMOVE: to the beginning of a line, and */ 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.

Making Macros More General

In some C++ programs, you will often find constructs which resemble the following:

for (bool
...
}

The only difference from one occasion to the next is the set of names: cont, iterator, value and the content in between the curly brackets.

If you insert the above code often, you may wish to build a macro to help you with this. Your first attempt may be to define a macro, which simply inserts:

for (bool =.First(); ; =.Next()) {
}

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 cont three times and iterator and value two times each. What you really would like is to have Emacs ask you which names to use. You can do that with macros. The trick is called “recursive editing”. With recursive editing, you can tell Emacs to stop at a specific place in the macro, do some editing, and when done, tell Emacs to continue with the macro.

When you record macros, you tell Emacs to enter recursive editing by pressing CRTL-u CTRL-x q. Then whenever you execute the macro, Emacs will stop macro execution at that point to let you do some editing, and then the macro will continue when you press CTRL-META-c. (If there is no META key on your keyboard, it is most likely the ALT key instead.)

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 CTRL-u CTRL-x q until you press CTRL-META-c will not be part of the macro.

We are almost ready to develop a neat and useful macro, but first let's exercise what we've learned so far with a simple example. Type the following: CTRL-x ( Type a word ==> CTRL-u CTRL-x q.

Now type Hello World, and when done, continue typing the following: CTRL-META-CTRL <== CTRL-x )

The above inserted the following text into your buffer:

Type a word ==>Hello World<==
Furthermore, it also defined a macro, which inserts this text except for the words “Hello World”. Whenever you execute the just-defined macro, Emacs will pause after having inserted Type a word ==>, and when you press CTRL-META-c, it will continue with the macro, which means it will insert the text <==.

Can you see where we are heading? Now we have the tools to ask the user for the three names needed, so now all we need is a way to fetch the information he typed and insert it at the appropriate places.

Fetching the information could be done several ways. The simplest (that is, the one which requires the least knowledge of Emacs) would simply be to switch to a temporary buffer, let the user type in the information there, and whenever one of the words is needed, simply go to this buffer and fetch it there.

A much smarter way is to use registers. 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 CTRL-x r s and a letter (the letter indicates the register in which to save the information). Later, you may insert the contents of the register into the buffer by pressing CTRL-x r i and pressing the letter you typed above.

Listing 1

Listing 1 shows all the keystrokes needed to record this macro. Text in between quotes should be typed literally, and text in italics is comments, which should not be typed. It may seem like a lot of typing 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.

Power-Macros

Power Macros is an Emacs package, which I developed out of frustration at not being able to define a macro, bind it to a key, and have it bound for future Emacs sessions (or rather, not being able to do so easily).

To use this Emacs package, download the file from its home page at http://www.imada.sdu.dk/~blackie/emacs/. Copy the Lisp file to a location in your load path, and insert the following into your .emacs file:

(require 'power-macros)
(power-macros-mode)
(pm-load)

If you do not know what a load path is, or do not have one, create a directory called Emacs in your home directory, copy the file to this directory, and insert the following line into your .emacs file before the lines above:

(setq load-path (cons "~/Emacs" load-path))
When that is done, you may simply press CTRL-c n when you have defined a macro, and Emacs will ask you the following questions in the mini-buffer.

Which key to bind the macro to? First, Emacs must know to which key the macro should be bound. When you are finished answering these questions, the macro will be available simply by pressing this key. By binding to different keys, you can have several macros defined at the same time.

How should the macro be accessible? With power-macros, you may make the macro accessible in one of two ways:

  1. Global: it is accessible in every buffer.

  2. A major-mode-specific macro: the macro is accessible only in buffers with a given major mode.

As an example of a mode-specific macro, think about the for-loop macro from the example above. This macro is useful only when writing C++ programs. Furthermore, you may need a similar macro using Java syntax for programming Java. With power-macros, you may bind both the macro for C++-mode and the macro for Java-mode to the same key (say CTRL-m-f); then the correct one will be used for the given mode.

Which file should it be saved to? By default, Emacs saves the macros defined with power-macro to the file named ~/.power-macros. If that is okay for the macro you are defining, simply press ENTER at this question. If you do not want to save the given macro to a file for future Emacs sessions, remove the suggested text (i.e., answer the question with an empty string). Also, you can name another file. The section below has a description of when doing this can be of special interest.

What is its description? 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 forgotten which key it is bound to, or when you are searching for a key to bind a new macro.

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 and ask for confirmation to continue the definition.

Local Macros

Some time ago, I was going to give a speech on Emacs. I have previously made that a number of times, so I hadn't done any special preparation for this specific speech. While I was traveling to the event by train, I decided to go through my presentation. I was terrified to see that the presentation program suddenly didn't work on my machine. What should I do? The answer was 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? The answer was to create two macros: one going forward one page, and another going backward one page.

Going forward one page was done in the following way:

  • Search for a line starting with a number of equal signs, namely the second line of each presentation page (just below the title of the page).

  • Press CTRL-1 CTRL-l (that is, control-(number)one control-(letter)l). This would locate this line as the second line of the screen, and consequently, the title of the page would be the first one.

  • Go to the beginning of the next line. This was necessary so that the subsequent search would not find the current page.

The two macros just defined are useful only for the given file, and later for all files which contain 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 time, especially given that there might be several months before my next Emacs presentation.

The two macros were therefore saved to a separate file, and whenever needed, I can simply load them. Loading a power-macro is done by using the function pm-load. Thus, I could load the macros by pressing META-x, 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 automatically by inserting the following lines as the last lines of the file:

Local Variables:
eval: (pm-load "presentation.macro")
End:

Here, it is assumed that the name of the file containing the macros is called presentation.macro. Now, Emacs automatically loads the presentation macros whenever the file is opened.

Managing Power-Macros

When you have defined a number of macros, you might want to perform various functions to manage your macros. This is done by pressing CTRL-c m. It will bring up a buffer like:

the one shown in Figure 1.

What you see in this buffer is your power-macros, each separated with a line of dashes. Many keys have special meanings in this buffer (just like the keys have special meanings in the buffer-managing buffer or in the dired buffer).

Pressing the ENTER key on top of one of the fields allows you to edit the given field. Editing a field means either to change its content or 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.

Emacs Macros and the Power-Macros Package

Figure 1. Emacs Power-Macro Buffer

Deletion of macros is done in two steps. First, you mark the macros you want to delete, and next you tell Emacs to actually delete them. If you know either the buffer-managing buffer or dired-mode, you will be familiar with this two-step process.

If you are now ready to learn more about Emacs, visit my home page at the URL mentioned earlier.

This article was first published in Issue 47 of LinuxGazette.com, an on-line e-zine formerly published by Linux Journal.

Emacs Macros and the Power-Macros Package
Jesper Pedersen Jesper Pedersen is the author of the book Teach Yourself Emacs in 24 Hours, the program “The Dotfile Generator”, the Emacs package “Power Macros”, and is chairman for the Linux User Group on Funen in Denmark.
Load Disqus comments

Firstwave Cloud