файлы макросов в системе набора GNU roff (macro files in the GNU roff typesetting system)
Writing macros
A roff(7) document is a text file that is enriched by predefined
formatting constructs, such as requests, escape sequences,
strings, numeric registers, and macros from a macro package.
These elements are described in roff(7).
To give a document a personal style, it is most useful to extend
the existing elements by defining some macros for repeating
tasks; the best place for this is near the beginning of the
document or in a separate file.
Macros without arguments are just like strings. But the full
power of macros occurs when arguments are passed with a macro
call. Within the macro definition, the arguments are available
as the escape sequences \$1
, ..., \$9
, \$[
...]
, \$*
, and \$@
, the
name under which the macro was called is in \$0
, and the number
of arguments is in register \n[.$]
; see groff(7).
Draft mode
Writing groff macros is easy when the escaping mechanism is
temporarily disabled. In groff, this is done by enclosing the
macro definition(s) within a pair of .eo
and .ec
requests. Then
the body in the macro definition is just like a normal part of
the document — text enhanced by calls of requests, macros,
strings, registers, etc. For example, the code above can be
written in a simpler way by
.eo
.ds midpart was called with the following
.de print_args
\f[I]\$0\f[] \*[midpart] \n[.$] arguments:
\$*
..
.ec
Unfortunately, draft mode cannot be used universally. Although
it is good enough for defining normal macros, draft mode fails
with advanced applications, such as indirectly defined strings,
registers, etc. An optimal way is to define and test all macros
in draft mode and then do the backslash doubling as a final step;
do not forget to remove the .eo request.
Tips for macro definitions
• Start every line with a dot, for example, by using the
groff request .nop
for text lines, or write your own macro
that handles also text lines with a leading dot.
.de Text
. if (\\n[.$] == 0) \
. return
. nop \)\\$*\)
..
• Write a comment macro that works both for copy and draft
modes; since the escape character is off in draft mode,
trouble might occur when comment escapes are used. For
example, the following macro just ignores its arguments,
so it acts like a comment line:
.de c
..
.c This is like a comment line.
• In long macro definitions, make ample use of comment lines
or almost-empty lines (this is, lines which have a leading
dot and nothing else) for a better structuring.
• To increase readability, use groff's indentation facility
for requests and macro calls (arbitrary whitespace after
the leading dot).
Diversions
Diversions can be used to implement quite advanced programming
constructs. They are comparable to pointers to large data
structures in the C programming language, but their usage is
quite different.
In their simplest form, diversions are multi-line strings, but
diversions get their power when used dynamically within macros.
The (formatted) information stored in a diversion can be
retrieved by calling the diversion just like a macro.
Most of the problems arising with diversions can be avoided if
you remember that diversions always store complete lines. Using
diversions when the line buffer has not been flushed produces
strange results; not knowing this, many people get desperate
about diversions. To ensure that a diversion works, add line
breaks at the right places. To be safe, enclose everything that
has to do with diversions within a pair of line breaks; for
example, by explicitly using .br
requests. This rule should be
applied to diversion definition, both inside and outside, and to
all calls of diversions. This is a bit of overkill, but it works
nicely.
(If you really need diversions which should ignore the current
partial line, use environments to save the current partial line
and/or use the .box
request.)
The most powerful feature using diversions is to start a
diversion within a macro definition and end it within another
macro. Then everything between each call of this macro pair is
stored within the diversion and can be manipulated from within
the macros.