Skip to content

ds26gte/mpca

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 

Repository files navigation

mpca

Introduction

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”.

Installation

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 *.tmac files to your home directory.

The pca-t2p-*.tmac files are used only if you process your documents with troff2page. They are not needed for groff. If you don’t plan to use troff2page, you don’t need to put them in GROFF_TMAC_PATH. The other pca*.tmac files are used by both groff and troff2page.

Invocation

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.

Init file

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.)

Verbatim display

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.

Image

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.)

Page cross-references

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.

Table of contents

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.

Index

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

  1. alternate alphabetization,

  2. subitems,

  3. literal metacharacters, and

  4. 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 calls is essentially the same as for LaTeX, except that in groff we use

.IX item

where in LaTeX one would use

\index{item}
Note
For full details on index-entry syntax, consult the makeindex documentation.

Bibliography

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]].

Eval

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.

Lua

.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.

Common Lisp

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.

JavaScript

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

Aux files

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.

Using only some of mpca’s features

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.

Adding OpenType Fonts to groff

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages