groff: Writing Macros
5.21 Writing Macros
===================
A "macro" is a collection of text and embedded commands that can be
invoked multiple times. Use macros to define common operations. ⇒
Strings, for a (limited) alternative syntax to call macros.
Although the following requests can be used to create macros, simply
using an undefined macro will cause it to be defined as empty. ⇒
Identifiers.
-- Request: .de name [end]
-- Request: .de1 name [end]
-- Request: .dei name [end]
-- Request: .dei1 name [end]
Define a new macro named NAME. 'gtroff' copies subsequent lines
(starting with the next one) into an internal buffer until it
encounters the line '..' (two dots). If the optional second
argument to 'de' is present it is used as the macro closure request
instead of '..'.
There can be whitespace after the first dot in the line containing
the ending token (either '.' or macro 'END'). Don't insert a tab
character immediately after the '..', otherwise it isn't recognized
as the end-of-macro symbol.(1) (⇒Writing Macros-Footnote-1)
Here 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
..
The following example defines a macro within another. Remember
that expansion must be protected twice; once for reading the macro
and once for executing.
\# a dummy macro to avoid a warning
.de end
..
.
.de foo
. de bar end
. nop \f[B]Hello \\\\$1!\f[]
. end
..
.
.foo
.bar Joe
=> Hello Joe!
Since '\f' has no expansion, it isn't necessary to protect its
backslash. Had we defined another macro within 'bar' that takes a
parameter, eight backslashes would be necessary before '$1'.
The 'de1' request turns off compatibility mode while executing the
macro. On entry, the current compatibility mode is saved and
restored at exit.
.nr xxx 12345
.
.de aa
The value of xxx is \\n[xxx].
..
.de1 bb
The value of xxx is \\n[xxx].
..
.
.cp 1
.
.aa
=> warning: number register `[' not defined
=> The value of xxx is 0xxx].
.bb
=> The value of xxx is 12345.
The 'dei' request defines a macro indirectly. That is, it expands
strings whose names are NAME or END before performing the append.
This:
.ds xx aa
.ds yy bb
.dei xx yy
is equivalent to:
.de aa bb
The 'dei1' request is similar to 'dei' but with compatibility mode
switched off during execution of the defined macro.
If compatibility mode is on, 'de' (and 'dei') behave similar to
'de1' (and 'dei1'): A 'compatibility save' token is inserted at the
beginning, and a 'compatibility restore' token at the end, with
compatibility mode switched on during execution. ⇒Gtroff
Internals, for more information on switching compatibility mode
on and off in a single document.
Using 'trace.tmac', you can trace calls to 'de' and 'de1'.
Note that macro identifiers are shared with identifiers for strings
and diversions.
⇒the description of the 'als' request als, for possible
pitfalls if redefining a macro that has been aliased.
-- Request: .am name [end]
-- Request: .am1 name [end]
-- Request: .ami name [end]
-- Request: .ami1 name [end]
Works similarly to 'de' except it appends onto the macro named
NAME. So, to make the previously defined 'P' macro actually do
indented instead of block paragraphs, add the necessary code to the
existing macro like this:
.am P
.ti +5n
..
The 'am1' request turns off compatibility mode while executing the
appended macro piece. To be more precise, a "compatibility save"
input token is inserted at the beginning of the appended code, and
a "compatibility restore" input token at the end.
The 'ami' request appends indirectly, meaning that 'gtroff' expands
strings whose names are NAME or END before performing the append.
The 'ami1' request is similar to 'ami' but compatibility mode is
switched off during execution of the defined macro.
Using 'trace.tmac', you can trace calls to 'am' and 'am1'.
⇒Strings, for the 'als' and 'rn' request to create an alias
and rename a macro, respectively.
The 'de', 'am', 'di', 'da', 'ds', and 'as' requests (together with
their variants) only create a new object if the name of the macro,
diversion or string is currently undefined or if it is defined to be a
request; normally they modify the value of an existing object.
-- Request: .return [anything]
Exit a macro, immediately returning to the caller.
If called with an argument, exit twice, namely the current macro
and the macro one level higher. This is used to define a wrapper
macro for 'return' in 'trace.tmac'.
Menu