summaryrefslogtreecommitdiff
path: root/info/digests/texline/no12/victor.tex
blob: 8195e16d46a4cbf3eda6230f045c48048f53363b (plain)
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
 
\chardef\busje=`\\
\def\cs#1{{\tt\busje#1}}
%\newcommand{\whiteline}{\medskip\noindent}

{\overfullrule0pt\everypar{\looseness0}\title{\bf A parskip scheme}
While I was working on the \LaTeX\ styles described
in Braams {\it et al\/}, it became apparent to me that lots of people are rather
fond of the sort of layout
that can be described as
\begintt
\parindent=0cm
\parskip=6pt % or other positive size
\endtt
Unfortunately, most of them realize this layout by no more sophisticated
means than simply inserting these two lines at the beginning
of the input. The drawback of such a simple action is
that all sorts of vertical spaces are augmented by the
\cs{parskip} when there is absolutely no need to,
or where it is positively unwanted. Examples of this
are the white space below section headings,
and the white space above and
below list environments in \LaTeX.
 
In this article I will present an approach that unifies the
paragraph skip and the
white spaces surrounding various environments.
Since the macros given below make use of the \cs{everypar}
token list, this article may be seen as a sequel to
an earlier paper on an indentation scheme (Eijkhout, 1990),
which is based on a similar principle.
The \cs{everypar} parameter was explained there.
 
\section{\cs{\ttit parskip}} 
\TeX\ starts a paragraph when it switches from
vertical to horizontal mode. The vertical mode
may have been initiated by a \cs{par} (for instance
because of an empty line after a preceding paragraph)
or by a vertical skip command; the switch to horizontal
mode can be effected by, for example, a character
or a horizontal skip command (see the list in Knuth (1984, p283).
Immediately above the first line of the paragraph
\TeX\ will then add glue
of size \cs{parskip}
to the vertical list, unless this paragraph is
at the start of a vertical list, for instance at the
start of a vertical box or insertion item.
 
Apparently, then, the \cs{parskip} parameter is very
simple to use. That this is only an apparent
simplicity becomes  clear in a number of instances.
 
For instance, unless precautions are taken, the white
space below headings is augmented by the paragraph skip.
Precautions against this are not particularly elegant:
the easiest solution is to include a
\begintt
\vskip-\parskip
\endtt
statement, to backspace the paragraph skip in advance.
Such an approach, however, is somewhat error-prone.
Vertical spacing  will be messed up if what follows is not
a paragraph, but a display formula or a box.
 
Similar considerations apply to the amounts of white space
that surround, for example, list environments, as in \LaTeX.
 
\section{Paragraph skip: to be or not to be}
Ordinarily in plain \TeX\ and in \LaTeX\ the paragraph
skip is set to {\tt 0pt plus 1pt}, which gives pages some
`last resort' stretchability. However, even an amount of vertical
space as small as one point may become very
visible, and often without need (see for instance
the first page of the preface of the \TB).
 
Furthermore, Stanley Morison (1936) states that not indenting
paragraphs is `decidedly an abject method'.
However, reading his intention instead of his words,
he is only concerned with the recognizability of the individual
paragraphs. The positive value of the paragraph skip is sufficient
to ensure this. If a layout is based on zero values for
both \cs{parindent} and \cs{parskip}, one may for instance
give the \cs{parfillskip} a positive natural width
to prevent last lines of a paragraph from almost, or completely,
lining up with the right margin.
 
Neither Donald Knuth nor Leslie Lamport
seem to have given much thought to
the case where the paragraph skip has a positive natural width.
Leslie Lamport dismisses all potential difficulties with the remark
that `it is customary not to leave any extra space
between paragraphs' (Lamport, 1986, p94).
 
\section{Environments and white lines}
Given that the paragraph skip appears to interact with
explicit vertical spacing in user macros, it may seem
like a good idea to find a unified approach to both.
In the rest of this article I will describe the implementation
of the following basic idea: {\em give the paragraph skip
the value zero whenever you do an explicit vertical skip}.
 
For this paper  I assume a context with  some form of
environments. These are the assumptions that I make
about such environments:

\item{$\bullet$} An environment is a portion of material that is vertically
separated from whatever is before and after it. Thus, according to
this definition, a portion of a paragraph cannot be an environment,
nor can an environment start or end in the middle of a paragraph.
\item{$\bullet$} An environment has associated with it three glue parameters:
to an environment {\tt foo} correspond \cs{fooStartskip} (glue
above the environment), \cs{fooParskip} (the paragraph skip
inside the environment), and the \cs{fooEndskip} (glue below
the environment). 
\item{$\bullet$} At the outset of the environment
a 
\begintt
\StartEnvironment{foo}
\endtt
 statement
is executed; at the end of the environment a macro
\begintt
\EndEnvironment{foo}
\endtt
 is executed.
These statements are assumed to
contain a \cs{begingroup} and \cs{endgroup}
respectively.

\noindent
Such assumptions are sufficiently general for the macros
below to be adaptable to existing macro packages.
At first sight it would appear as if section headings
are not covered by the above points. However, there
is no argument against the start and end of an environment
occurring in the same macro.
 
\section{Tools} 
First I will present two auxiliary macros: \cs{csarg}
and \cs{vspace}.
 
The command \cs{csarg}
is only needed inside other macros; it is meant to
enable constructs such as
\begintt
\csarg\vskip{#1Parskip}
\endtt
Its definition is
\begintt
\def\csarg#1#2{\expandafter
    #1\csname#2\endcsname}
\endtt
By way of explanation of this macro, consider a simple example.
Let us assume that there exists a macro
\begintt
\def\startlist#1{ ...
    \csarg\vskip{#1Startskip}
    ...}
\endtt
The call 
\begintt
\startlist{enumerate}
\endtt
will then lead to the following call to \cs{csarg}:
\begintt
\csarg\vskip{enumerateStartskip}
\endtt
This expands to
\begintt
\expandafter\vskip
 \csname enumerateStartskip\endcsname
\endtt
Now the \cs{expandafter} forces \cs{csname} to be executed
before the \cs{vskip}, so the next step of the expansion
looks like
\begintt
\vskip\enumerateStartskip
\endtt
and this statement can simply be executed.
 
Next I need a generalization of \cs{vskip}, which I will call \cs{vspace}:
a number of calls to \cs{vspace} should have the effect
that only the maximum argument is placed.
\begintt
\newskip\tempskipa
\def\vspace
 #1{\tempskipa=#1\relax
   \ifvmode\ifdim\tempskipa<\lastskip
      \else\vskip-\lastskip
      \vskip\tempskipa
      \fi
   \else \vskip\tempskipa\fi}
\endtt
This may need some explanation. By the assignment
|\tempskipa=#1| I allow the argument of \cs{vspace} to be
both a control sequence, for instance \cs{parskip},
and a denotation, for instance {\tt 5pt plus 3pt}.
If one omits the assignment, the latter option would cause trouble
in the \cs{ifdim} test.
 
The decision to keep the maximum value of the skip, instead of
always replacing the last skip, was motivated by phenomena
such as a display formula at the end of a list. If the
skip below the display is larger than the vertical glue
below the list (which may be zero),
the former should be retained entirely.
\looseness1
 
Note that this macro can insert vertical space of size
zero. This will for instance happen if it follows
a \cs{par} command at the end of a paragraph.
It is then called in vertical mode,
but the last item on the vertical list is a box
(the last line of the paragraph) instead of a
glue item. The parameter \cs{lastskip} will then be zero.
 
\section{The environment macros} 
In this section, I will give the implementation of the
macros \cs{StartEnvironment} and \cs{EndEnvironment}.
 
There is a remarkable similarity between these two macros.
As I explained above, the basic idea is to have only explicit
spacing above and below the environment; thus, the value of \cs{parskip}
should then be zero both for the first paragraph in the
environment, and for the first paragraph that follows it.
Both macros should then
   \item{$\bullet$} save the current value of the paragraph skip;
   \item{$\bullet$} set the paragraph skip to zero;
   \item{$\bullet$} give \TeX\ a signal that, somewhere in the near
   future, the old value of \cs{parskip} is to be restored.

\noindent For this I allocate a skip register and a conditional:
\begintt
\newskip\TempParskip
\newif\ifParskipNeedsRestoring
\endtt
The basic sequence for both macros is then
\begintt
\TempParskip=\parskip
\parskip=0cm\relax
\ParskipNeedsRestoringtrue
\endtt
 
\noindent For both macros, however, this sequence needs to be
refined slightly.
 
The paragraph skip to be `restored' at the start of the
environment is the specific value associated with that
environment. This gives us:
\begintt
\def\StartEnvironment
 #1{\csarg\vspace{#1Startskip}
    \begingroup %% make changes local
    \csarg\TempParskip{#1Parskip}
    \parskip=0cm\relax
    \ParskipNeedsRestoringtrue}
\endtt
Note that the statement
\begintt
\csarg\TempParskip{#1parskip}
\endtt
denotes an assignment (without an optional equals sign) here.
 
At the end of the environment we have to be more careful.
It may be the case that
the environment being ended was inside another
environment, and occurred
before the first paragraph inside
that environment. In that case the value of \cs{parskip} is zero,
and the proper value must still be restored.
Therefore, no further actions are required.

We arrive at the following implementation:
\begintt
\def\EndEnvironment
 #1{\csarg\vspace{#1Endskip}
    \endgroup %% restore global values
    \ifParskipNeedsRestoring
    \else \TempParskip=\parskip
          \parskip=0cm\relax
          \ParskipNeedsRestoringtrue
    \fi}
\endtt
Note that both macros start with a vertical skip. This prevents
the \cs{begingroup} and \cs{endgroup} statements from
occurring in a paragraph. 

On a side note: since these macros
are executed in vertical mode, I have not bothered to terminate
any lines with comment signs. Any spaces generated by
these macros are ignored in vertical mode.
 
\section{Paragraph skip restoring}
So far, I have ignored one important question:
how exactly is restoring the paragraph skip implemented.
For this I use the \cs{everypar} token list.
Basically then, the idea is the same as in (Eijkhout, 1990):
the occurrence of a paragraph will  automatically
have \TeX\ perform, through the insertion of the
\cs{everypar} tokens, the actions necessary for subsequent
paragraphs.
\begintt
\everypar=
   {\ControlledIndentation
      %see Tugboat 11, #3
    \ControlledParskip}
\def\ControlledParskip
   {\ifParskipNeedsRestoring
       \parskip=\TempParskip
       \ParskipNeedsRestoringfalse
    \fi}
\endtt
The cost of a controlled paragraph skip is then one conditional
per paragraph. Conceivably, this cost could even be reduced further
(to almost zero) by defining
\begintt
\def\CPS % Controlled Parskip
   {\ifParskipNeedsRestoring
       \parskip=\TempParskip
       \ParskipNeedsRestoringfalse
       \let\ControlledParskip=\relax
    \fi}
\endtt
and including a statement
\begintt
\let\ControlledParskip=\CPS
\endtt
in both the \cs{StartEnvironment} and
\cs{EndEnvironment} macros, and at the start of the job (for instance
by including it in the macro package).
This approach, however, does not particularly
appeal to me. Too much `pushing the bit around'.
 
\section{Conclusion}
The \cs{parskip} parameter is arguably the most tricky parameter of
\TeX. Its workings are very easy to describe, but in actual
practice difficulties arise. In this article I have
described how treatment of the paragraph skip can be integrated
with the glue above and below environments.
As in an earlier article on indentation, I use for this
the \cs{everypar} parameter as an essential tool.
 
\section{Bibliography} 
{\frenchspacing\parindent0pt\everypar{\hangindent20pt\hangafter1}\par
Johannes Braams, Victor Eijkhout \& Nico A.F.M. Poppelier,  1989, 
The development of national \LaTeX\ styles,
TUGboat 10(3) (1989), pp401--406.
 

Victor Eijkhout, 1990,
An indentation scheme, TUGboat 11(4).
 

Donald Knuth, 1984, The \TeX book,
Addison-Wesley Publishing Company.

 

Stanley Morison, 1936, First principles of typography,
Cambridge University Press.
 

Leslie Lamport, 1986, \LaTeX, a document preparation
system, Addison-Wesley Publishing Company.

}} 

\author{Victor Eijkhout}
\endinput
Victor Eijkhout                     phone: +1 217 244-0047
 Center for Supercomputing Research and Development
 University of Illinois at Urbana-Champaign
 305 Talbot laboratory
 104 South Wright street
 Urbana, Illinois 61801-2932, USA
 
home: 2503 W. Springfield Av, Apt. K-4, Champaign 61821, USA