Macros

So far we've considered several different types of macros. A macro is usually a terse, two or three-character sequence specified on a macro line. In this section I formalise the various types of macros, categorised by their scope rules. As with many other languages, macros instructions are either scoped to one line (following a single instruction), which I call in-line; or to multiple lines (bracketed between instructions), which I call blocked. Block macros are usually invoked on a line of their own, as with Bd, but may also be invoked within a line.

Generally speaking, a macro is syntactically defined as having a macro name, and optionally flags and with optional flag arguments. The arguments to a macro depend on its scope rules.

Name Flag Arg

The hyphen - indicates a macro flag only when the preceding macro accepts arguments.

In-line Macro

An in-line macro's arguments are scoped to the current line. Its scope may also be closed out by subsequent macros: an in-line macro can never contain a nested macro. For a complete reference, see In-Line macros in the mdoc reference.

Name Flag Flag Arg Arg...

Not all in-line macros accept arguments, and some in-line macros accept a fixed number of arguments.

For example, the regular way of structuring command-line arguments, as described initially in the Elaborate Function guide, is a command flag, followed by flag arguments, followed by regular arguments. We can put most invocation forms on one line as follows.

.Op Fl W Ns Ar level

In this example, Ar, Fl, and Ns are in-line macros. The Op is a block partial-implicit. The Fl macro opens within the Op and is closed by the Ns, which accepts no arguments at all. This suppresses the space between the flag and its arguments (this alternative style is used at times, but discouraged). The arguments are opened by Ar and close at the end of the line.

The following is an example of macros with a fixed number of arguments:

.Xr mandoc 1 Ap s

The Xr macro accepts the mandoc and 1 arguments, then reverts to accepting text. The Ap accepts no arguments, so it immediately reverts to the trailing text.

Finally, an example of an in-line macro accepting flags follows:

.St ansiC

The argument to St specifies the standard to be printed.

Block Partial Implicit

A block partial macro is similar to an in-line macro in that its scope is restricted to the current line: it is implicitly closed by the end of line (as opposed to block partial explicit macros) and partial in that it only extends to the current line (as opposed to block full implicit macros). Unlike an in-line macro, it accepts nested macros (hence block macro). For a complete reference, see Block Partial Implicit macros in the mdoc reference.

Name Flag Flag Arg Arg|Macro...

The scope of a partial block macro is always closed by the end of the line; any macros between it and the end of line are interpreted as nested macros. We began this book with the block partial implicit macro Qq. The nested qualities of this macro category may be seen by embedding Qq and Pq

.Pq Qq Parenthesised quotation .

Be warned. If you open but do not close a block partial explicit macro before the end of the line, behaviour is not always well-defined as the scope is broken.

Block Full Implicit

A macro seen early on, the Sh macro, is block full implicit. Unlike block partial implicit macros, these consist of multiple lines (they are blocks) and treat the line arguments and multi-line arguments differently (full). For a complete reference, see Block Full Implicit macros in the mdoc reference.

.Begin Flag Flag Arg Arg...
Arg...

The scope of Begin is closed out implicitly — by one of several possible macros or the end of file. The notion of a full macro is obvious when considering Sh:

.Sh SECTION 1
Sectional text.
.Sh SECTION 2
Sectional text.

In this, the macro must separately decorate its line arguments and multi-line arguments. In this case, the line arguments must be bolded while the multi-line arguments must be indented. The Sh macro is closed out by a subsequent Sh or the end of file. Compare this to Ss, which closes out with a subsequent Sh, Ss, or end of file.

Block Partial Explicit

The simplest multi-line macro is the block partial explicit, which is opened and closed by two separate (explicit) macros. It is partial because it does not differentiate between arguments on the current line or subsequent lines, as opposed to block full explicit macros. The pair of macros involved in a full block macro are called the beginning and ending macros. For a complete reference, see Block Partial Explicit macros in the mdoc reference.

.Begin Flag Flag Arg Arg...
Arg...
.End

One must be careful, in full block macros, not to break the scope of other block macros, or behaviour is undefined.

We have not yet considered a block partial explicit macro pair in this book. But we can do so by considering Oo and Oc. This pair of macros, for option open and option close, extend the behaviour of Op to multiple lines.

.Fl W Oo
warn|error|fatal
.Oc

Block Full Explicit

The block full explicit macros are full in the sense that arguments on the macro line and arguments following are treated differently (like block full implicit macros). The earliest example of this is the Bl. These macros are explicitly closed by a closing macro and may contain nested macros. For a complete reference, see Block Full Explicit macros in the mdoc reference.

Consider the Bd macro, which does not accept line arguments (most block full explicit macros do not accept line arguments). It is manually closed by Ed.

.Bd ragged offset indent
Display text.
More display text.
.Ed

In this example, the text between the Bd and Ed are treated specially.

Last edited by $Author: kristaps $ on $Date: 2011/12/25 15:03:57 $. Copyright © 2011, Kristaps Dzonsons. CC BY-SA.