Next: Macro Packages, Previous: Tabs and Leaders, Up: Text [Contents][Index]
The foregoing describes almost all of the syntax of the
roff
language,30
with an exception already noted
in passing.
A
request
is an instruction to the formatter that occurs after a
control character,
which is recognized at the beginning of an input line.
The regular control character is a dot
(.).
Its counterpart,
the
no-break control character,
a neutral apostrophe
('),
suppresses the break that some requests imply.
These characters were chosen
because it is uncommon for lines of text in natural languages
to begin with them.
If you require a formatted period or apostrophe
(closing single quotation mark)
where the formatter expects a control character,
prefix the dot or neutral apostrophe
with the dummy character escape sequence,
‘\&’.
An input line beginning with a control character is called a control line. Every line of input that is not a control line is a text line.31
Requests often take arguments, words (separated from the request name and each other by spaces) that specify details of the action you expect the formatter to perform.
Requests and escape sequences comprise the control language of the formatter. Of key importance are the requests that define macros. Macros are invoked like requests, permitting extension or override of the request repertoire.32
Think of a macro as an abbreviation you can define for a collection of control and text lines. When a document calls a macro by placing its name after a control character, the formatter replaces the control line with the macro’s definition. The process of textual replacement is known as interpolation.33 The formatter performs an interpolation upon recognition, and once performed, it scans the replacement for further requests, macro calls, and escape sequences.
In
roff
systems,
the
de
request defines a macro.34
.de DATE 2020-11-14 ..
The foregoing input produces no output by itself;
all we have done is store information in a macro named
‘DATE’.
Observe the pair of dots that ends the macro definition.
This is a default;
you can specify your own terminator for the macro definition
as the second argument to the
de
request.
.de NAME ENDNAME Heywood Jabuzzoff .ENDNAME
In fact, the ending mark is itself the name of a macro to be called, or a request to be invoked, if it is defined at the time its control line is read.
.de END
Big Rip
..
.de START END
Big Bang
.END
.START
⇒ Big Rip Big Bang
In the foregoing example, “Big Rip” printed before “Big Bang”
because its macro was called first. Consider what would happen
if we dropped END from the ‘.de START’ line and added
.. after .END. Would the order change?
Let us consider a more elaborate example.
.de DATE
2020-10-05
..
.
.de BOSS
D.\& Kruger,
J.\& Peterman
..
.
.de NOTICE
Approved:
.DATE
by
.BOSS
..
.
Insert tedious regulatory compliance paragraph here.
.NOTICE
Insert tedious liability disclaimer paragraph here.
.NOTICE
⇒ Insert tedious regulatory compliance paragraph here.
⇒
⇒ Approved: 2020-10-05 by D. Kruger, J. Peterman
⇒
⇒ Insert tedious liability disclaimer paragraph here.
⇒
⇒ Approved: 2020-10-05 by D. Kruger, J. Peterman
The above document started with a series of control lines.
Three macros were defined,
with a
de
request declaring each macro’s name,
and the
body
of the macro starting on the next line
and continuing until a line with two dots
‘..’
marked its end.
The text proper began only after the macros were defined;
this is a common pattern.
Only the
NOTICE
macro was called “directly” by the document;
DATE
and
BOSS
were called only by
NOTICE
itself.
Escape sequences were used in
BOSS,
two levels of macro interpolation deep.
The advantage in typing and maintenance economy may not be obvious from such a short example, but imagine a much longer document with dozens of such paragraphs, each requiring a notice of managerial approval. Consider what must happen if you are in charge of generating a new version of such a document with a different date, for a different boss. With well-chosen macros, you only have to change each datum in one place.
In practice, we would probably use strings (see Strings) instead of macros for such simple interpolations; what is important here is to glimpse the potential of macros and the power of recursive interpolation.
We could have defined our
DATE
and
BOSS
macros in the opposite order;
perhaps less obviously,
we could also have defined them
after
NOTICE.
Such “forward references” are well-defined
because the body of a macro definition is,
for the most part,
stored rather than interpreted
(see Copy Mode).
While a macro is being defined
(or appended to),
requests are not interpreted and macros not interpolated;
some commonly used escape sequences
are
however interpreted.
roff systems also support recursive macro calls, as long as you
have a way to break the recursion (see Conditionals and Loops).
Maintainable roff documents tend to arrange macro definitions to
minimize forward references.
Next: Macro Packages, Previous: Tabs and Leaders, Up: Text [Contents][Index]