1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
|
.so g.tmac
.
.\" configure header and footer
.eo
.de @h
. sp |36p
. if \n%>1 .tl ''-%-''
. sp |1i
..
.
.de @f
. sp |\n(.pu-48p
. tl ''\*(#e''
..
.ec
.
.\" configure environments
.@e p
. nr sq \n(sp
. nr sp 0
.@e l
. fam M
. vs +1p
.@e n
. @c p
. ta 3n +3n +3n +3n
.@e
.
.\" define macros
.eo
.de n
. if !'\$1'' \{\
. nr ni \$1-1
. af ni 0
. if !'\$2'' .af ni \$2
. ds n. .
. if !'\$3'' .ds n. \$3
. \}
. nr ni +1
. br
. @e n
. ti \n(tiu
\n(ni\*(n. \c
..
.ec
.
.\" start document
.t
.x Mg ,
a simple macro package for troff
.d
John Ankarstr\(:om
.d e
.
.
.h
Introduction
.p
.i Mg
is a simple macro package for troff with the following features:
.n 1
It is designed to be easy to understand and to customize
by editing the source code.
.n
It makes use of the extended support for environments
offered by many modern troff implementations.
.n
It is designed to be practically easy to use.
Macros are consistently one letter long and written in lowercase.
.p
While
.i mg
does provide macros for many common tasks,
including footnotes,
it is at the end of the day an idiosyncratic macro package,
written to serve the author's personal needs.
Users of
.i mg
are encouraged to
.n 1 a )
modify the source code
according to their own needs, as well as
.n
use built-in troff requests for some things
that other packages might provide custom macros for.
.p
All in all,
.i mg
aspires to abstract as little as possible
from the underlying troff requests and registers.
In its author's humble opinion,
it is the ideal macro package for learning troff.
.p
In this document, the fundamental concepts of
.i mg
are explained.
The reader is encouraged to inspect the document's source code
in order to see how the macro package is used in practice.
.
.
.h
Environments
.p
.i Mg
makes heavy use of named environments,
supported by implementations such as GNU troff and Neatroff.
Environments obliviate the need for many special registers
that a macro package (and its user) would otherwise need to keep track of.
For example,
.i ms
keeps track of the document's font size in the
.c PS
register.
For the font size of headings,
it has yet another register.
.i Mg
has no such registers.
If the user wishes to modify the default font size,
he or she can simply switch to the relevant environment
and set the font size as desired
using regular troff requests:
.l
\&.\\" set heading font
\&.h
\&.fam H
\&.ps +1p
.p
Troff saves the font settings in the environment,
so that the next time the environment is invoked,
the desired font family and point size are automatically restored.
.p
The environments are initialized
as soon as the first
.q block-level
macro is called.
At the initialization of each environment,
the default environment (0) is copied,
meaning that all environment-relevant settings
defined before the first macro call
are applied to all
.i mg
environments.
It is thus remarkably simple and intuitive to set,
for example, the default font of a document:
.l
\&.fam N
\&.t
Document title
\&.p
First paragraph.
.p
In addition to the normal environment-relevant settings,
.i mg
manually associates a few special registers with the current environment:
.n 1
.c sp ,
the amount of vertical space to add before an environment
.n
.c sq ,
the amount of vertical space to add before a different type of environment
.n
.c ti ,
the indentation of the first line in some environments
(currently only
.c p )
.p
These can be set inside a given environment
to control its behavior when invoked.
The only exception are the margin and footnote environments
.c @m , (
.c @f ),
which are treated specially
and do not support these registers.
.
.
.h
External macros
.p
.i Mg
defines a number of macros.
Some of them are used internally by
.i mg
itself;
these carry an at
.c @ ) (
prefix
and are going to be explored later.
For now, we will focus on the external macros provided by
.i mg .
.s
Inline macros
.p
There is a group of macros that provide
convenient inline formatting.
All take three arguments:
the text to be formatted,
the text to be placed immediately after
and the text to be placed immediately before.
The inline macros are the following:
.n 1
.c b ,
bold font
.n
.c c ,
constant-width font
.n
.c i ,
italic font
.n
.c i ,
bold italic font
.p
For example, the following request outputs
.i mg .\(rq: \(lq
.l
\&.i mg .
.
.p
Note that
.c c
uses the font family and point size
set in the
.c l
environment (see below).
.s
Block-level macros
.p
There is a large group of macros that provide
block-level formatting:
.n 1
.c d ,
centered date or text
.n
.c h ,
heading
.n
.c l ,
literal display (for source code)
.n
.c p ,
paragraph
.n
.c s ,
subheading
.n
.c t ,
centered title
.p
The
.c t
and
.c d
macros can be used at the beginning of a document
to create a centered header:
.l
\&.t
Document title
\&.d
First author
\&.br
Second author
\&.d i \\" current date formatted as YYYY-MM-DD
.p
In the example above, you can see that the
.c d
macro may be used for other things than just dates.
This works because
.c d
displays the date only if given
an argument describing the desired date format:
.n 1 a )
.c i :
international date, like
.q 2021-06-21
.n
.c e :
English date, like
.q "21 June 2021"
.p
The formatted dates are defined in strings prefixed with a hash symbol
.c # ): (
.c #i
and
.c #e
are provided by default,
but more may be added by the user.
.
.s
Other macros
.p
Finally, there are a few macros
that belong to neither category:
.n 1
.ne 2
.c ( ,
begin footnote
.n
.c ) ,
end footnote
.n
.ne 2
.c q ,
quotation
.n
.c w ,
want space
.p
The macros
.c (
and
.c )
create footnotes,
placing a numerical reference at the place of their invocation.
Both
.c (
and
.c )
take an optional argument,
which is output either immediately before or immediately after
the inline reference.
For example, the following code
.l
\&.q
This is a quotation\\c
\&.(
.ne 1
This is a footnote.
\&.) .
.p
creates the following reference:
.q
This is a quotation\c
.(
This is a footnote.
.) .
.p
If
.c (
and
.c )
are called at such a position that the collected footnotes
cannot fit on the current page,
.i mg
will print the footnotes on the next page instead.
.p
The
.c q
behaves like an inline macro by default,
surrounding text in quotation marks,
but if no arguments are given to it,
it starts an indented block quotation instead:
.l
.ne 2
\&.q
This is an indented quotation.
\&.p
This is an inline
\&.q quotation .
.p
The
.c w
macro is an alternative to troff's
.c ne
request,
which ensures that a given amount of space is available on the page
\(en otherwise, a line break is issued \(en
but unlike
.c ne ,
which takes an exact amount of space as its argument,
.c w
takes a declarative specification
describing the amount of desired space
in terms of
.i mg
environments.
For example:
.l
\&.\\" want space for...
\&.w s p \\" a subheading of one line + a paragraph of one line
\&.w s pp \\" a subheading of one line + a paragraph of two lines
\&.w ss p \\" a subheading of two lines + a paragraph of one line
.
.
.h
Internal macros
.p
.i Mg 's
internal macros are generally not meant to be used outside of
.i g.tmac .
Documented in this section are the exceptions to this rule.
For examples of how these macros are used in practice,
see the FAQ section below.
.
.s
Margin macros
.p
The
.c @h ,
.c @f ,
.c @th
and
.c @tf
macros control the page header and footer.
.p
At document initialization,
.i mg
automatically creates traps for
.c @th
and
.c @tf .
When sprung,
.c @th
and
.c @tf
call
.c @h
and
.c @t ,
which control the text and spacing of the header and footer.
.p
.i Mg
will avoid creating a trap for
.c @tf
if any trap has already been set before document initialization.
This means that users can override the position of the
.c @tf
trap by setting it themselves.
Likewise, users can redefine
.c @h
and
.c @f
to change the content of the header and footer.
.
.s
Environment macros
.p
The environment-related macros
.c (e ,
.c @e
and
.c @c
may be used in advanced documents to define custom environments.
.p
At the present,
.c (e
is nothing more than a wrapper around troff's built-in
.c ev ,
but it may eventually be redefined in order to offer
compatibility with implementations of troff
without support for named environments.
.p
.c @e
and
.c @c
are equivalent to troff's
.c ev
and
.c evc ,
but perform some extra work to keep track of
.i mg 's
special environment variables
(see
.i Environments
above).
.
.
.h
Frequently anticipated questions
.
.s
How do I customize the default appearance of a document?
.p
All environment settings,
like point size, font family and indentation\c
.(
For a complete list of settings that are associated with the environment,
see 5.26\~\c
.i Environments
in the full GNU troff manual
.nh
.c "info '(groff.\:info)Environments'" ). (
.hy
.) ,
are configured with the standard troff requests.
If you set the point size at the beginning of the document,
before any
.i mg
macros have been called,
it will be correctly set for the entire document.
This works because
.i mg 's
environments initially copy all their settings from 0,
the default environment.
.p
For example, if you wanted to write a document
with the New Century Schoolbook font
at 9 points
and a vertical spacing of 12 points,
you would start the document like this
(before you call any
.i mg
macros):
.l
\&.fam N
\&.ps 9p
\&.vs 12p
.
.s
How do I customize the default appearance of a given environment?
.p
To configure the layout and font settings of a specific environment,
you can switch to that environment and use the relevant troff requests:
.l
.ne 1
\&.q
\&.ps +1p
.p
If you are merely configuring the environment
without printing anything in it,
you can also use the
.c @e
macro:
.l
\&.@e q
\&.ps +1p
.
.w s ll
.s
How do I customize the default appearance of the margin text?
.l
\&.(e @m \\" margin environment
\&.ps +1p
.p
You can also set such settings in your redefinition of
.c @h
or
.c @f .
.
.w s ll
.s
How do I customize the default appearance of footnotes?
.l
\&.(e @f \\" footnote environment
\&.ps +1p
.
.s
How do I redefine the page header?
.l
\&.de @h
\&. \\" set position of header text
\&. sp |36p
\&. \\" set header text
\&. tl 'left'center'right'
\&. \\" set position of page text
\&. sp |1i
\&..
.
.s
How do I redefine the page footer?
.l
\&.\\" set position of footer trap
\&.\\" (must be done before any macros have been called)
\&.wh -1i @tf
\&.
\&.de @f
\&. \\" set position of footer text
\&. \\" (must be below the footer trap)
\&. sp |\\\\n(.pu-48p
\&. tl 'left'center'right'
\&..
.
.s
How do I prevent a section from being broken up by a page break?
.p
Some macro packages have a concept of
.q keeps ,
sections that are kept together across page breaks.
.i Mg
does not define any such macros by default.
The simplest way to achieve the same is to use troff's
.c ne
request:
.l
\&.ne 7 \\" break page if seven lines won't fit on this page
\&.\\" ... some text ...
.p
If you want to keep text of various styles together,
you can use
.i mg 's
own
.c w
macro:
.l
\&.w s qq \\" break page if a subheading and two lines of a quotation won't fit
\&.\\" ... some text ...
.ig
.p
For a more general solution, you can use a diversion:
.l
\&.di keep
\&.\\" ... some text ...
\&.br
\&.di
\&.ne \\n(dnu
\&.keep
..
.
.s
How do I define my own environments?
.p
Environments are a feature built into troff,
accessed via the
.c ev
request, but because
.i mg
extends environments with additional functionality,
it provides special macros to be used instead of
.c ev :
.n 1
.c (e ,
set environment (same as
.c ev )
.n
.c @e ,
set extended environment
.n
.c @c ,
copy environment (same as
.c evc )
.p
The
.c @e
macro
can be used to activate any environment that supports
.i mg 's
extensions (see
.i Environments
above).
The following code configures an environment called
.c n
and defines a corresponding macro:
.l
\&.@e n
\&. @c 0 \\" copy default environment
\&. ps -1p
\&.@e
\&.
\&.de n
\&. br \\" finish current environment
\&. @e n \\" activate new environment
\&..
|