Next: Page Motions, Previous: Conditionals and Loops, Up: GNU troff Reference [Contents][Index]
A macro is a stored collection of text and control lines that can be interpolated multiple times. Use macros to define common operations. Macros are called in the same way that requests are invoked. While requests exist for the purpose of creating macros, simply calling an undefined macro, or interpolating it as a string, will cause it to be defined as empty. See Identifiers.
Define a macro name, replacing the definition of any existing
request, macro, string, or diversion called name. If
name already exists as an alias, the target of the alias is
redefined; recall Strings. GNU troff enters copy
mode,151 storing subsequent input lines as the
macro definition. If the optional second argument is not specified, the
definition ends with the control line ‘..’ (two dots).
Alternatively, end identifies a macro whose call syntax at the
start of a control line ends the definition of name; end is
then called normally. A macro definition must end in the same
conditional block (if any) in which it began (recall see Conditional Blocks). Spaces or tabs are permitted after the control character in
the line containing this ending token (either ‘.’ or
‘end’), but a tab immediately after the token prevents its
recognition as the end of a macro definition. The macro end can
be called with arguments.152
Here is a small example macro called ‘P’ that causes a break and inserts some vertical space. It could be used to separate paragraphs.
.de P . br . sp .8v ..
We can define one macro within another. Attempting to nest ‘..’ naïvely will end the outer definition because the inner definition isn’t interpreted as such until the outer macro is later interpolated. We can use an end macro instead. Each level of nesting should use a unique end macro.
An end macro need not be defined until it is called. This fact enables a nested macro definition to begin inside one macro and end inside another. Consider the following example.153
.de m1
. de m2 m3
you
..
.de m3
Hello,
Joe.
..
.de m4
do
..
.m1
know?
. m3
What
.m4
.m2
⇒ Hello, Joe. What do you know?
A nested macro definition can be terminated with ‘..’ and nested macros can reuse end macros, but these control lines must be escaped multiple times for each level of nesting. The necessity of this escaping and the utility of nested macro definitions will become clearer when we employ macro parameters and consider the behavior of copy mode in detail.
de defines a macro that inherits the compatibility mode
enablement status of its context (see Implementation Differences).
Often it is desirable to make a macro that uses groff features
callable from contexts where compatibility mode is on; for instance,
when writing extensions to a historical macro package. To achieve this,
compatibility mode needs to be switched off while such a macro is
interpreted—without disturbing that state when it is finished.
The de1 request defines a macro to be interpreted with
compatibility mode disabled. When name is called, compatibility
mode enablement status is saved; it is restored when the call completes.
Observe the extra backlash before the interpolation of register
‘xxx’; we’ll explore this subject in Copy Mode.
.nr xxx 12345
.de aa
The value of xxx is \\n[xxx].
. br
..
.de1 bb
The value of xxx is \\n[xxx].
..
.cp 1
.aa
error→ warning: register '[' not defined
⇒ The value of xxx is 0xxx].
.bb
⇒ The value of xxx is 12345.
The dei request defines a macro with its name and end
macro indirected through strings. That is, it interpolates strings
named name and end before performing the definition.
The following examples are equivalent.
.ds xx aa .ds yy bb .dei xx yy
.de aa bb
The dei1 request bears the same relationship to dei as
de1 does to de; it temporarily turns compatibility mode
off when name is called.
am appends subsequent input lines to macro name, extending
its definition, and otherwise working as de does.
To make the previously defined ‘P’ macro set indented instead of block paragraphs, add the necessary code to the existing macro.
.am P .ti +5n ..
The other requests are analogous to their ‘de’ counterparts. The
am1 request turns off compatibility mode during interpretation of
the appendment. The ami request appends indirectly, meaning that
strings name and end are interpolated with the resulting
names used before appending. The ami1 request is similar to
ami, disabling compatibility mode during interpretation of the
appended lines.
Using trace.tmac, you can trace calls to de,
de1, am, and am1. You can also use the
backtrace request at any point desired to troubleshoot tricky
spots (see Debugging).
See Strings, for the als, rm, and rn requests to
create an alias of, remove, and rename a macro, respectively.
Macro identifiers share their name space with requests, strings, and
diversions; see Identifiers. The am, as, da,
de, di, and ds requests (together with their
variants) create a new object only if the name of the macro, diversion,
or string is currently undefined or if it is defined as a request;
normally, they modify the value of an existing object. See the
description of the als request, for pitfalls when redefining a
macro that is aliased.
Stop interpreting an interpolated macro,
skipping to the end of its definition.
Do not confuse
return
with
rt.
If called with an argument
input,
GNU
troff performs the skip twice—once within the macro being interpreted
and once in an enclosing macro,
permitting a macro to wrap the request.154
| • Parameters | ||
| • Copy Mode |
Next: Page Motions, Previous: Conditionals and Loops, Up: GNU troff Reference [Contents][Index]