Путеводитель по Руководству Linux

  User  |  Syst  |  Libr  |  Device  |  Files  |  Other  |  Admin  |  Head  |



   groff_tmac    ( 5 )

файлы макросов в системе набора GNU roff (macro files in the GNU roff typesetting system)

  Name  |  Description  |  Macro packages  |  Naming  |  Inclusion  |    Writing macros    |  See also  |

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.