The venerable typesetter groff is ubiquitous. With the standard
package ms
, it lets you create a wide variety of documents in
plain text with your favorite text editor. It lacks some basic
features, however, viz., cross references, table of contents, and
index.
The mpca
macro package is an unobtrusive extension of the
standard ms
package that provides workable defaults for these
basic needs which can be extended or overridden as needed.
mpca
may stand for “Macros for the Prevention of Cruelty to
Authors”.
Get the mpca
package from GitHub:
git clone https://github.com/ds26gte/mpca
Inside the directory mpca
, the subdirectory tmac
contains the
macro file pca.tmac
and several subfiles pca-*.tmac
.
Either include this directory in your GROFF_TMAC_PATH
, or add
the *.tmac
files here to some directory in your
GROFF_TMAC_PATH
.
Tip
|
If you’re just experimenting, you could simply copy the
The |
To use mpca
, you can simply source pca.tmac
at the head of
your document:
.mso pca.tmac
Alternatively, you can use the groff
command-line option -m
,
e.g.,
% groff -mpca doc.ms > doc.ps
Other groff
options can be added as usual.
Let’s now go into the mpca
features that you can use in your document.
mpca
will source a macro file .groffrc.tmac
if it can find it in
your GROFF_TMAC_PATH
or home directory.
~/.groffrc.tmac
is a good place to put minor customizations that are
relevant only to your system. (E.g., I find I sometimes need to
slightly tweak the page-offset register (PO
) to suit a
particular printer — this tweak needn’t or shouldn’t be enshrined
in my document.)
Use .EX
to start and .EE
to end a verbatim display, typically
used for program listings, e.g.,
.EX function fact(n) if n == 0 then return 1 else return n*fact(n - 1) end end .EE
In this style of call, a display is allowed to cross page
boundaries. You can’t use the backslash (\
) without triggering
a troff escape. You also can’t use a period (.
) in the first
column of any line in the display. This is typically not a
problem if you consistently indent the body of your displays
anyway. (Periods in the middle of lines are ok.)
You can use a leading period to effect styling changes. For example
.EX function fact(n) .ft CI -- returns the factorial of n .ft C if n == 0 then return 1 else return n*fact(n - 1) end end .EE
Adding an argument to .EX
(doesn’t matter what, say 1
) lets
you use backslash verbatim in the display, however this requires
the display to fit in one page. (The reason is that groff’s page boundary
traps require the troff escape enabled.)
In the general .EX
(without argument), you can briefly
turn off the troff escape with .eo
, as long as you quickly
(before danger of a page boundary) turn
it back on with .ec
. These lines of course use .
in the
first column and will not be themselves displayed.
The .IMG
macro can be used to insert image files. The syntax
follows that of the .IMG
macro in the www.tmac
, but (a) isn’t
restricted to HTML output. E.g.,
.IMG t2p.png
sources the image t2p.png
.
You can specify the image alignment with an optional first argument: -L
for left, -R
for right, -C
for centered. If no alignment is
specified, -C
is assumed.
.IMG -L t2p.png
.IMG
takes an optional final argument to specify the width of
the image. The default is 1 inch.
.IMG t2p.png 3i .IMG -L t2p.png 4i
.IMG
relies on the external programs convert
(from
ImageMagick); mkbitmap
and potrace
(both from the Potrace
package); and Inkscape. (mkbitmap
and potrace
are needed
for PNG images. Inkscape is needed for SVG
images.)
The .TAG
macro manages cross-references. E.g.,
.TAG sec_grofflua
associates the label TAG:sec_grofflua
with the number of the
current page. The string \*[TAG:sec_grofflua]
is defined to
typeset as that page number. Thus, in a hand-crafted table of
contents, you could use
Extending groff using Lua, \*[TAG:sec_grofflua]
.TAG
takes an optional second argument. The label is then
associated with the text of the second argument instead of the
current page number.
Note
|
mpca ’s .TAG overrides a similarly named macro in
the file www.tmac in the groff distribution, which only
allows backward references.
|
Important
|
.TAG requires two runs of groff . Please see the
section on aux files.
|
The .ToC
macro inserts a table of contents (ToC). Add your own
header, e.g., “Contents”, or “Table of Contents” (which is also
the default value of the ms
string \*[TOC]
).
.ToC
does not require you to modify how you use your sectioning
macros — it automatically draws its information from the
distribution of the .NH
and .SH
macros within your document.
It is thus a solution to the following statement from the groff
manual:
Altering the ‘NH’ macro to automatically build the table of contents is perhaps initially more difficult, but would save a great deal of time in the long run if you use ‘ms’ regularly.
ToC entries are generated for the usual ms
section headers (.SH
,
.NH
). The depth of the ToC is governed by the number register
GROWPS
: Only those .SH
/.NH
headers at a level less than or
equal to GROWPS
will go into the ToC.
The number register \n[pca:DI]
(default: .5 inch) determines
how much subsections are indented in the ToC.
The .IX
macro is used to generate index entries:
.IX item to be indexed
marks the text “item to be indexed” as an indexable item. The sorted index made from these entries can be sourced into the input document via
.so \*[AUXF].ind
Adding a section header on top is up to you.
The sorted index is constructed using the external program
makeindex
. makeindex
is included in TeX distributions, but
you can also obtain it as
a
standalone package.
The metacharacters @
, !
, "
, and |
can be used
to respectively specify
-
alternate alphabetization,
-
subitems,
-
literal metacharacters, and
-
encapsulation of the page number.
E.g.,
.IX m@-m, groff option
identifies an index entry for “-m, groff option” but alphabetizes it as though it were “m” rather than something that starts with a hyphen.
.IX groff!macro packages
makes “macro packages” an indented index subentry under “groff”.
Up to two !
s may be used.
.IX groff!macro packages!ms
produces “ms” as a subsubentry under “macro packages” under “groff”.
.IX troff|see groff
has the index entry for “troff” point to “groff” rather than have a page number of its own.
If any of the metacharacters need to
appear in the index entry as themselves, precede them with "
.
.IX set"!car
creates an index entry for “set!car” rather than creating a subentry “car” under “set"”.
Tip
|
The syntax for .IX item where in LaTeX one would use \index{item} |
Note
|
For full details on index-entry syntax, consult the makeindex documentation. |
The .BIB
macro is used to introduce a paragraph that is a simple bibliographic
reference, e.g.,
.BIB utp David S. Landes, \fIRevolutions in Time: Clocks and the Making of the Modern World\fP, Belknap Press, 1983.
If it is the nth such reference in the document, it is prefixed
with “[n]” in the output. Furthermore, the label TAG:utp
is
associated with n, using the cross-reference mechanism
described earlier, and can be used to cite the reference. E.g.,
For a history of the first portable device that, for better or worse, completely changed how we live, see Landes [\*[TAG:landes_clock]].
The macro .eval
allows you to insert Lua, Common Lisp or JavaScript
code in your document to guide its transformation via
groff. In other words, it lets you you use Lua, CL, or JS to
extend groff instead of relying purely on groff macros.
The code inside .eval
is evaluated using the language specified
by the string pca-eval-lang
, which by default is lua
.
We will first describe the Lua version of .eval
.
.eval
does only one thing: It allows you to place arbitrary
Lua code until the following .endeval
, and the text written to
the stream troff
this Lua code is substituted for the .eval …
.endeval
. The usefulness of this tactic will be apparent from an
example. Consider the following document, tau.ms
:
The ratio of the circumference of a circle to its radius is \(*t \(~= .eval -- the following prints tau, because cos(tau/2) = -1 troff:write(2*math.acos(-1), '.\n') .endeval
Run it through mpca
:
groff -z -U -mpca tau.ms
The -z
avoids generating ouput, because we’re not ready for it
yet. The -U
runs groff
in “unsafe” mode, i.e., it allows the
writing of aux files.
You will find that the groff
call produces the following
message:
Rerun groff with -U
Call groff
again as folows:
groff -U -mpca tau.ms > tau.ps
tau.ps
will now look like:
The ratio of the circumference of a circle to its radius is τ ≈ 6.2831853071796.
Here’s how it works. The first groff
call produces a Lua file
\*[AUXF].lua
that collects all the .eval
code in the
document. The second groff
call invokes Lua to create an aux
file for each .eval
and sources it back into the document.
It should be clear that Lua code via .eval
can serve as a very
powerful second extension language for groff. For a more
substantial example of .eval
’s use see
the troff2page manual.
To use Common Lisp inside .eval
, set
.ds pca-eval-lang lisp
in your document before the first use of .eval
. Thus, the
tau.ms
file, translated to Common Lisp, will now read:
.ds pca-eval-lang lisp The ratio of the circumference of a circle to its radius is \(*t \(~= .eval ;the following prints tau, because cos(tau/2) = -1 (princ (* 2 (acos -1)) *troff*) (princ "." *troff*) (terpri *troff*) .endeval
Note
|
For the Common Lisp .eval , we write to the stream
*troff* rather than troff .
|
To use JavaScript inside .eval
, set
.ds pca-eval-lang js
in your document before the first use of .eval
. Thus, the
tau.ms
file, translated to JavaScript, will now read:
.ds pca-eval-lang js The ratio of the circumference of a circle to its radius is \(*t \(~= .eval // the following prints tau, because cos(tau/2) = -1 troff.write('' + 2*Math.acos(-1)); troff.write('.\n'); .endeval
mpca
uses auxiliary (aux) files to implement its
cross-referencing, ToC, indexing, and eval features.
The troff string \*[AUXF]
is used to construct the names of
these auxiliary files. By default this is quietly set to .trofftemp
.
You can change it to something else (provided it satisfies
your OS’s file-naming conventions) in your document before the first use of
any macros that use or write aux files.
Aux files are created in one run of groff
and slurped back in
during a second run. Thus groff
needs to be run twice for the
defined feature to take effect. Furthermore, the first run of
groff
must be run in “unsafe” mode (groff
option -U
) as
groff
won’t create external files in “safe” mode.
Tip
|
You may ignore this section if you don’t mind loading all of
the mpca features.
|
You may pick and choose individual features of mpca
without committing to the rest of it.
To do this source one or more of the following
macro files:
pca-eval.tmac
(eval),
pca-img.tmac
(images),
pca-ix.tmac
(index),
pca-sc.tmac
(thought break),
pca-tag.tmac
(cross-references),
and
pca-toc.tmac
(ToC).
E.g.,
.mso pca-eval.tmac
If the feature uses aux files, you will need to run groff
twice, once in unsafe mode,
as described in the section on aux files.