Reference Documentation: PDF Publishing with GNU Troff
修訂 | a01868c021e548e9fd93d910e39deadc8c7f774e (tree) |
---|---|
時間 | 2022-03-30 04:12:08 |
作者 | ![]() |
Commiter | Keith Marshall |
Implement a more effective TOC generation strategy.
* tmac/toc.tmac: New file; it implements a basic, extensible,
table of contents generator macro framework; use it...
* pdfmark.ms (XH-UPDATE-TOC): ...here; modify it to generate...
(pdfmark.toc): ...this new file, subsequently included and used by...
(toc.outline, toc.refmark, toc.pageref): ...these new document-local
toc.tmac extending macros, to generate TOC in-line, superseding...
(TC): ...use of this spdf.tmac macro; delete reference.
[TOC] (PDFHREF.TEXT.COLOUR): Set it to match...
(\n[.m]): ...this.
* Makefile.in (pdfmark.pdf): Update dependencies, requiring...
(pdfmark.toc): ...this new intermediate file; add rules to generate
it, by performing a separate pre-processing pass over...
(pdfmark.ms): ...this primary source file.
(clean): Remove "*.toc" files.
@@ -83,8 +83,8 @@ | ||
83 | 83 | # We want to use the locally maintained groff macro files, as those in |
84 | 84 | # the system's groff installation may not be sufficiently up-to-date. |
85 | 85 | # |
86 | +pdfroff := pdfroff | |
86 | 87 | tmacdir := ${srcdir}/tmac |
87 | -pdfroff := GROFF_TMAC_PATH=${tmacdir} pdfroff | |
88 | 88 | |
89 | 89 | vpath %.ms ${srcdir} |
90 | 90 | vpath %.tmac ${srcdir}/tmac |
@@ -92,13 +92,19 @@ | ||
92 | 92 | # Specific prerequisites of "pdfmark.pdf", to be used... |
93 | 93 | # |
94 | 94 | pdfmark.pdf: style := --style=${srcdir}/cover.ms |
95 | -pdfmark.pdf: gnu.eps spdf.tmac s.tmac pdfmark.tmac sanitize.tmac | |
95 | +pdfmark.pdf pdfmark.toc: spdf.tmac s.tmac pdfmark.tmac sanitize.tmac toc.tmac | |
96 | +pdfmark.pdf: gnu.eps pdfmark.toc | |
97 | + | |
98 | +override pdfroff := GROFF_TMAC_PATH=${tmacdir} $(pdfroff) | |
96 | 99 | |
97 | 100 | # ...in conjunction with this generic build rule. |
98 | 101 | # |
99 | 102 | %.pdf: %.ms |
100 | 103 | $(pdfroff) -mspdf $(style) -dpaper=a4 -P-pa4 $< > $@ |
101 | - | |
104 | + | |
105 | +%.toc: %.ms | |
106 | + $(pdfroff) -U -mspdf --no-pdf-output -dpaper=a4 -P-pa4 $< | |
107 | + | |
102 | 108 | # We require copies of embeddable artwork files to be accessible |
103 | 109 | # via references in the working build directory. |
104 | 110 | # |
@@ -109,7 +115,7 @@ | ||
109 | 115 | # ------------- |
110 | 116 | # |
111 | 117 | clean mostlyclean: |
112 | - $(RM) *.pdf | |
118 | + $(RM) *.pdf *.toc | |
113 | 119 | |
114 | 120 | distclean: clean |
115 | 121 | $(RM) config.* *.eps |
@@ -85,19 +85,160 @@ | ||
85 | 85 | .nr DI 5n |
86 | 86 | .nr HY 0 |
87 | 87 | . |
88 | -.\" Within the table of contents, the width of the right-hand margin, | |
89 | -.\" in which space is reserved for the display of page numbers, and the | |
90 | -.\" appearance of the leaders which precede it, are controlled by:- | |
91 | -.\" | |
92 | -.char \[TC-LEADER] \h'0.8n'. | |
93 | -.nr TC-MARGIN \w'00000' | |
94 | -. | |
95 | 88 | .\" Generate headers in larger point sizes, for NH levels < 4, |
96 | 89 | .\" with point size increasing by 1.5p, for each lesser NH level. |
97 | 90 | .\" |
98 | 91 | .nr GROWPS 4 |
99 | 92 | .nr PSINCR 1.5p |
100 | 93 | . |
94 | +.\" Immediately following the cover sheet, and front-matter, is the | |
95 | +.\" conventional placement for the table of contents; we begin this | |
96 | +.\" on a new page, with a centred heading, which we have choosen to | |
97 | +.\" set at a font size 2pts greater than that of normal paragraphs, | |
98 | +.\" (thus matching standard "ms" convention), with lower case roman | |
99 | +.\" numerals for page numbering, with its own entry within the PDF | |
100 | +.\" document outline, and with the equivalent of two blank lines | |
101 | +.\" separating the heading from the TOC references. | |
102 | +.\" | |
103 | +.af % i | |
104 | +.LP | |
105 | +.ce 1 | |
106 | +.pdfhref O 1 \\*[TOC] | |
107 | +.\"pdfhref O -N toc 1 \\*[TOC] | |
108 | +.B "\s'+2p'\*[TOC]\s'-2p'" | |
109 | +.sp 2v | |
110 | +.\" | |
111 | +.\" The traditional mechanism, supported by "ms", for generation of | |
112 | +.\" tables of contents, relies on post-press collation, to print the | |
113 | +.\" table of contents AFTER the document body, and then to relocate | |
114 | +.\" it to its conventional position, BEFORE the body content. | |
115 | +.\" | |
116 | +.\" While pdfroff DOES support such post-press collation, it is not | |
117 | +.\" the most effective method for placement of the tables of contents | |
118 | +.\" within PDF documents. Although a method for use of the technique | |
119 | +.\" is described, in Section 3 of this document, it is not the actual | |
120 | +.\" method employed; in particular, it has been found to be unsuited | |
121 | +.\" to the creation of a table of contents which is actively linked | |
122 | +.\" to its corresponding body content. Consequently, the preferred | |
123 | +.\" method of table of contents generation is now to save relevant | |
124 | +.\" reference data during the pdfroff pre-press phase, and then to | |
125 | +.\" reimport it during the body content publication phase, using | |
126 | +.\" the toc.tmac macros, integrated with pdfroff... | |
127 | +.\" | |
128 | +.mso toc.tmac | |
129 | +.if \n[.U] .toc file pdfmark.toc | |
130 | +.\" | |
131 | +.\" ...by means of the following integration hooks, and auxillary | |
132 | +.\" helper script, (noting that this bypasses groff's "safer" mode | |
133 | +.\" protection, WITHOUT requiring the "-U" option): | |
134 | +.\" | |
135 | +.\"ds TOC.REQUEST gropdf-info:toc | |
136 | +.\"pdfroff option $AWK -f pdfmark.toc.awk $WRKFILE > pdfmark.tmp | |
137 | +.\" | |
138 | +.\" Within the table of contents, structural layout will be achieved, | |
139 | +.\" under the direction of the following spacing control constants: | |
140 | +.\" | |
141 | +.ds TC-VS1 0.40v \" leading for top level | |
142 | +.ds TC-VS2 0.15v \" leading at nesting level increment | |
143 | +.ds TC-VS3 0.25v \" leading following nested group | |
144 | +.\" | |
145 | +.\" Additionally, the width of the right-hand margin, in which space | |
146 | +.\" is reserved for the display of page numbers, and the appearance of | |
147 | +.\" the leaders which precede it, are controlled by:- | |
148 | +.\" | |
149 | +.nr TC-MARGIN \w'00000' | |
150 | +.char \[TC-LEADER] \h'0.8n'. | |
151 | +.lc \[TC-LEADER] | |
152 | +.\" | |
153 | +.\" Macro "toc.outline" initializes output state for each individual | |
154 | +.\" TOC reference entry, controlling indentation based on designated | |
155 | +.\" outline-level, as passed in the initiating XH-UPDATE-TOC call. | |
156 | +.\" | |
157 | +.de toc.outline | |
158 | +. ie \\$1>1 \{\ | |
159 | +. \" Entries at outline-levels greater than one are indented | |
160 | +. \" by 1em for each level; additionally, on increasing level | |
161 | +. \" from that of the preceding entry, as recorded in the local | |
162 | +. \" register, "toc.outline.current", additional vertical space | |
163 | +. \" equal to "TC-VS2" is inserted, while on decreasing to any | |
164 | +. \" level which remains greater than one, similar additional | |
165 | +. \" vertical space equal to "TC-VS3" is inserted. | |
166 | +. \" | |
167 | +. nr toc.indent \\$1m-1m | |
168 | +. ie \\$1>\\n[toc.outline.current] .sp \*[TC-VS2] | |
169 | +. el .if \\n[toc.outline.current]>\\$1 .sp \*[TC-VS3] | |
170 | +. nop \h'\\n[toc.indent]u'\c | |
171 | +. | |
172 | +. \" After emitting the appropriate indentation space, the | |
173 | +. \" tab-stop settings must be adjusted to compensate. | |
174 | +. \" | |
175 | +. nr toc.indent \\n[.l]-\\n[.i]-\\n[toc.indent] | |
176 | +. ta (u;\\n[toc.indent]-\\n[TC-MARGIN]) (u;\\n[toc.indent])R | |
177 | +. rr toc.indent | |
178 | +. \} | |
179 | +. el \{\ | |
180 | +. \" Entries at outline-level one are not indented, but each | |
181 | +. \" except the first, (identified by not yet having defined | |
182 | +. \" the "toc.outline.current" register), will be preceded by | |
183 | +. \" vertical space equal to "TC-VS1"; in any case, tab-stops | |
184 | +. \" are reset to match "ms" convention, in preparation for | |
185 | +. \" output of level one TOC entry. | |
186 | +. \" | |
187 | +. if r toc.outline.current .sp \*[TC-VS1] | |
188 | +. ta (u;\\n[.l]-\\n[.i]-\\n[TC-MARGIN]) (u;\\n[.l]-\\n[.i])R | |
189 | +. \} | |
190 | +. | |
191 | +.\" After initialization for the first TOC entry, tracking of the | |
192 | +.\" current outline-level is persistently maintained, by recording | |
193 | +.\" of the "toc.outline.current" register. | |
194 | +.\" | |
195 | +. nr toc.outline.current \\$1 | |
196 | +.. | |
197 | +.\" The collected TOC reference data is interpolated back into the | |
198 | +.\" document output stream, initially by the toc.refmark macro... | |
199 | +.\" | |
200 | +.de toc.refmark | |
201 | +. \" ...which simply stores the text for the TOC pageref entry, | |
202 | +. \" within the toc.refmark.text string, whence it is... | |
203 | +. \" | |
204 | +. ds \\$0.text \\$* | |
205 | +.. | |
206 | +.\" ...subsequently retrieved by the toc.pageref macro... | |
207 | +.\" | |
208 | +.de toc.pageref | |
209 | +. \" ...to be incorporated into an active pdfhref link, along | |
210 | +. \" with the appropriate page number reference, and emitted | |
211 | +. \" to the document output stream. | |
212 | +. \" | |
213 | +. pdfhref L -D \\*[toc.refmark.text]\a\t\\$* | |
214 | +. rm toc.refmark.text | |
215 | +. br | |
216 | +.. | |
217 | +.\" Although the TOC is to be entirely populated by active PDFHREF | |
218 | +.\" links, we prefer to not over-emphasize this by use of the link | |
219 | +.\" highlight colour; thus, after breaking the PDFHREF.TEXT.COLOUR | |
220 | +.\" to PDFHREF.TEXT.COLOR equivalence, we may adjust the effective | |
221 | +.\" link colour, to match the normal body text colour. | |
222 | +.\" | |
223 | +.rm PDFHREF.TEXT.COLOUR | |
224 | +.ds PDFHREF.TEXT.COLOUR \n(.m | |
225 | +.\" | |
226 | +.\" Actual content for the TOC has been dynamically captured in the | |
227 | +.\" pdfmark.toc file; simply include it here. | |
228 | +.\" | |
229 | +.so pdfmark.toc | |
230 | +.\" | |
231 | +.\" After output of the TOC, we may clear the PDFHREF.TEXT.COLOUR | |
232 | +.\" reassignment; the next call of pdfhref L, or of pdfhref W, will | |
233 | +.\" re-establish its equivalence to PDFHREF.TEXT.COLOR | |
234 | +.\" | |
235 | +.rm PDFHREF.TEXT.COLOUR | |
236 | +.\" | |
237 | +.\" Finally, reset the page numbering style, and prepare for output | |
238 | +.\" of the document body from page number one. | |
239 | +.\" | |
240 | +.af % 0 | |
241 | +.bp 1 | |
101 | 242 | . |
102 | 243 | .\" Implement an interface with the FS macro (from s.tmac) to facilitate |
103 | 244 | .\" placement of footnote reference marks, with each serving as an active |
@@ -254,13 +395,6 @@ | ||
254 | 395 | .\" the user-specified callback macro, XH-UPDATE-TOC, whereby it may |
255 | 396 | .\" be used, e.g. to construct a table of contents entry. |
256 | 397 | .\" |
257 | -.\" Within the table of contents, structural layout will be achieved, | |
258 | -.\" under the direction of the following spacing control constants: | |
259 | -.\" | |
260 | -.ds XNVS1 0.50v \" leading for top level | |
261 | -.ds XNVS2 0.15v \" leading at nesting level increment | |
262 | -.ds XNVS3 0.30v \" leading following nested group | |
263 | -.\" | |
264 | 398 | .\" Note that one TOC related callback hook is shared by both XH and |
265 | 399 | .\" XN; its is called XH-UPDATE-TOC, regardless of whether called by |
266 | 400 | .\" XH or by XN; when called by XN, it is invoked with arguments: |
@@ -268,55 +402,37 @@ | ||
268 | 402 | .\" .XH-UPDATE-TOC <outline-level> <section-number> <text> ... |
269 | 403 | .\" |
270 | 404 | .de XH-UPDATE-TOC |
271 | -.\" This implementation of XH-UPDATE-TOC utilizes the rudimentary ms | |
272 | -.\" mechanism for formatting a table of contents, using XS and XE to | |
273 | -.\" bracket individual entries. | |
274 | -. XS | |
275 | -. \" A local register, tc*hl, is used to track the outline level | |
276 | -. \" of each TOC entry, as it is added; it is not defined, until | |
277 | -. \" the first entry is recorded... | |
405 | +. \" Collection of TOC reference data is performed in pdfroff's | |
406 | +. \" pre-press phase, (before any PHASE indicator register value | |
407 | +. \" has been assigned); once PHASE has been assigned, this will | |
408 | +. \" simply appear as noise on standard error, so we may just as | |
409 | +. \" well suppress it. | |
278 | 410 | . \" |
279 | -. if r tc*hl \{\ | |
280 | -. \" ...after which, we use it to establish indentation, | |
281 | -. \" to reflect changes in outline level. | |
282 | -. \" | |
283 | -. ie \\$1>1 \{\ | |
284 | -. \" When at any outline level greater than one, | |
285 | -. \" any level increment will be offset by XNVS2 | |
286 | -. \" units of vertical space... | |
287 | -. \" | |
288 | -. ie \\$1>\\n[tc*hl] .sp \\*[XNVS2] | |
289 | -. | |
290 | -. \" ...whereas any decrement will be offset by | |
291 | -. \" XNVS3 units. | |
292 | -. \" | |
293 | -. el .if \\n[tc*hl]>\\$1 .sp \\*[XNVS3] | |
294 | -. \} | |
295 | -. | |
296 | -. \" ...but every top-level entry, after the first, is | |
297 | -. \" offset by XNVS1 units. | |
298 | -. \" | |
299 | -. el .sp \\*[XNVS1] | |
300 | -. \} | |
301 | -. | |
302 | -. \" \$1 becomes the effective outline level for the current table | |
303 | -. \" of contents entry, but we must ensure that it is one or more. | |
304 | -. \" | |
305 | -. ie \\$1 .nr tc*hl \\$1 | |
306 | -. el .nr tc*hl 1 | |
307 | -. | |
308 | -. \" The current outline level determines the indentation at which | |
309 | -. \" we place the section number reference... | |
310 | -. \" | |
311 | -. nop \h'\\n[tc*hl]-1m'\\$2\c | |
312 | -. | |
313 | -. \" ...after which we discard \$1 and \$2, allowing us to append | |
314 | -. \" all remaining arguments, ensuring that there is at least 0.5n | |
315 | -. \" of following space, before the first leader dot. | |
316 | -. \" | |
411 | +. if !\\n[PHASE] \{\ | |
412 | +. \" When collecting the reference data, we begin by storing | |
413 | +. \" the <outline-level>, the associated name assigned to the | |
414 | +. \" outline bookmark, and the <section-number> string... | |
415 | +. \" | |
416 | +. toc put outline \\$1 | |
417 | +. ds toc.refmark.text \\*[PDFBOOKMARK.NAME] -- \\$2 | |
418 | +. \" | |
419 | +. \" Having stored these two arguments, we discard them, so | |
420 | +. \" that we are left with only the <text> ... argument list, | |
421 | +. \" which we append to the collected TOC reference data... | |
422 | +. \" | |
317 | 423 | . shift 2 |
318 | -. nop \h'1.5n'\\$*\h'0.5n' | |
319 | -. XE | |
424 | +. toc put refmark \\*[toc.refmark.text]\h'1.5n'\\$*\h'0.5n' | |
425 | +. \" | |
426 | +. \" ...which is then completed, by the addition of a page | |
427 | +. \" number reference. | |
428 | +. \" | |
429 | +. toc put pageref \\n% | |
430 | +. \" | |
431 | +. \" Finally, clean up the temporary storage, which we have | |
432 | +. \" used to collect the TOC reference data. | |
433 | +. \" | |
434 | +. rm toc.refmark.text | |
435 | +. \} | |
320 | 436 | .. |
321 | 437 | .XN Introduction |
322 | 438 | .\" |
@@ -4602,7 +4718,7 @@ | ||
4602 | 4718 | . |
4603 | 4719 | .NH 3 |
4604 | 4720 | .XN -N import-map -- Deploying a Document Reference Map |
4605 | -.TC | |
4721 | +. | |
4606 | 4722 | .\" Local Variables: |
4607 | 4723 | .\" mode: nroff |
4608 | 4724 | .\" End: |
@@ -0,0 +1,115 @@ | ||
1 | +.\" -*- nroff -*- | |
2 | +.ig | |
3 | + | |
4 | +toc.tmac | |
5 | + | |
6 | +A minimal foundation macro framework, for construction of tables | |
7 | +of contents; provides the "toc" macro, with basic support for: | |
8 | + | |
9 | + .toc file [filename] | |
10 | + .toc put operation [arguments ...] | |
11 | + .toc error message ... | |
12 | + | |
13 | +This basic framework is extensible, by provision of user-supplied | |
14 | +auxiliary macros, with names of the form "toc.operation", to add | |
15 | +support for arbitrary operations, designated as: | |
16 | + | |
17 | + .toc operation [arguments ...] | |
18 | + | |
19 | + | |
20 | +Copyright (C) 2022, Free Software Foundation, Inc. | |
21 | + Written by Keith Marshall (keith.d.marshall@ntlworld.com) | |
22 | + | |
23 | + | |
24 | +This file is part of groff. | |
25 | + | |
26 | +groff is free software; you can redistribute it and/or modify it under | |
27 | +the terms of the GNU General Public License as published by the Free | |
28 | +Software Foundation; either version 2, or (at your option) any later | |
29 | +version. | |
30 | + | |
31 | +groff is distributed in the hope that it will be useful, but WITHOUT ANY | |
32 | +WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
33 | +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
34 | +for more details. | |
35 | + | |
36 | +You should have received a copy of the GNU General Public License along | |
37 | +with groff; see the file COPYING. If not, write to the Free Software | |
38 | +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. | |
39 | +.. | |
40 | +.if !\n(.g .ab These TOC macros require groff. | |
41 | +. | |
42 | +.\" Check if we have already been loaded -- do not reload | |
43 | +.if d toc.put .nx | |
44 | +. | |
45 | +.de toc | |
46 | +.\" Usage: .toc operation [argument ...] | |
47 | +.\" | |
48 | +.\" Primary entry point for user calls; performs a simple redirection | |
49 | +.\" to an appropriate handler for the specified operation, or emits an | |
50 | +.\" error diagnostic message, if no handler exists. | |
51 | +.\" | |
52 | +. ie d \\$0.\\$1 .\\$0.\\$* | |
53 | +. el .toc error \\$0: \\$1: unknown keyword | |
54 | +.. | |
55 | +. | |
56 | +.\" User adjustable configuration parameters... | |
57 | +. | |
58 | +.ds TOC.REQUEST .toc | |
59 | +. | |
60 | +.de toc.error | |
61 | +.\" Usage: .toc error message ... | |
62 | +.\" | |
63 | +.\" Emit a package-specific diagnostic message on the stderr stream. | |
64 | +.\" | |
65 | +. tm toc macro error: \\$* | |
66 | +.. | |
67 | +.de toc.file | |
68 | +.\" Usage: .toc file [filename] | |
69 | +.\" | |
70 | +.\" Assign a file, in which to collect TOC reference data; "filename" | |
71 | +.\" may be omitted, to close any previously assigned collection file, | |
72 | +.\" activating collection of subsequent reference data via "stderr". | |
73 | +.\" | |
74 | +.\" Note that data collection to a named file requires "groff" to be | |
75 | +.\" invoked with the "-U" option; this restriction does not apply to | |
76 | +.\" data collection via "stderr". | |
77 | +.\" | |
78 | +. if \\n[toc#stream] .close toc!stream | |
79 | +. nr toc#stream 0 | |
80 | +. als toc.put toc.put.tty | |
81 | +. if !'\\$1'' \{\ | |
82 | +. ie \\n[.U] \{\ | |
83 | +. open toc!stream \\$1 | |
84 | +. als toc.put toc.put.file | |
85 | +. nr toc#stream 1 | |
86 | +. \} | |
87 | +. el .toc error \\$1: unsafe mode required to write file. | |
88 | +. \} | |
89 | +.. | |
90 | +.de toc.put.file | |
91 | +.\" Usage: .toc put request arguments ... | |
92 | +.\" | |
93 | +.\" Service the .toc put request, when collecting such requests in | |
94 | +.\" a user designated file. Prefixed by the string which is defined | |
95 | +.\" as TOC.REQUEST, (which is ".toc" by default), the request and its | |
96 | +.\" arguments are copied to the designated file. | |
97 | +.\" | |
98 | +. write toc!stream \\*[TOC.REQUEST] \\$* | |
99 | +.. | |
100 | +.de toc.put.tty | |
101 | +.\" Usage: .toc put request arguments ... | |
102 | +.\" | |
103 | +.\" Service the .toc put request, when collecting such requests via | |
104 | +.\" the stderr output stream. Prefixed by the string which is defined | |
105 | +.\" as TOC.REQUEST, (which is ".toc" by default), the request and its | |
106 | +.\" arguments are copied to the stderr stream. | |
107 | +.\" | |
108 | +. tm \\*[TOC.REQUEST] \\$* | |
109 | +.. | |
110 | +.\" Initialize for default .toc request collection via stderr. | |
111 | +.\" | |
112 | +.toc file | |
113 | +. | |
114 | +. | |
115 | +.\" toc.tmac: end of file: vim: filetype=groff |