texit-leaders.tex /size: 5305 b    last modification: 2020-07-01 14:35
1\environment texit-style
2
3\startcomponent texit-leaders
4
5\startchapter[title={Leaders}]
6
7The following example comes from a question on the \CONTEXT\ list. It
8exhibits a few low level tricks. For the purpose of this example we
9use \type {\ruledhbox} instead of \type {\hbox}. We start with a simple
10command that puts something at the end of a line:
11
12\startbuffer
13\starttexdefinition MyFill #1
14    \removeunwantedspaces
15    \hfill
16    \ruledhbox{#1}
17\stoptexdefinition
18\stopbuffer
19
20\typebuffer[option=TEX] \getbuffer
21
22We use this in:
23
24\startbuffer[sample]
25\startitemize[packed,joinedup][rightmargin=3em]
26    \startitem
27        \samplefile{ward}\MyFill{DW}
28    \stopitem
29\stopitemize
30\stopbuffer
31
32\typebuffer[sample][option=TEX]
33
34and get:
35
36\getbuffer[sample]
37
38But, the requirement was that we move the number towards the right margin, so
39instead we need something:
40
41\startbuffer
42\starttexdefinition MyFill #1
43    \removeunwantedspaces
44    \hfill
45    \rlap{\ruledhbox to \rightskip{\hss#1}}
46\stoptexdefinition
47\stopbuffer
48
49\typebuffer[option=TEX] \getbuffer
50
51This already looks more like it:
52
53\getbuffer[sample]
54
55But also part of the requirements was that there should be dots between the end
56of the last sentence and the number. In low level \TEX\ speak that means using
57leaders: repeated boxed content where the repitition is driven by a glue
58specification. Let's naively use leaders now:
59
60\startbuffer
61\starttexdefinition MyFill #1
62    \leaders
63        \ruledhbox to 1em{\hss.\hss}
64        \hfill
65    \ruledhbox{#1}
66\stoptexdefinition
67\stopbuffer
68
69\typebuffer[option=TEX] \getbuffer
70
71Let's see what we get:
72
73\getbuffer[sample]
74
75Again we need to move the number to the right. This time we need a different
76solution because we need to fill the space in between. When \TEX\ ends a
77paragraph it adds \type {\parfillskip} so we will now manipulate that parameter.
78
79\startbuffer
80\starttexdefinition MyFill #1
81    \parfillskip-1\rightskip plus 1fil\relax
82    \leaders
83        \ruledhbox to 1em{\hss.\hss}
84        \hfill
85    \ruledhbox{#1}
86\stoptexdefinition
87\stopbuffer
88
89\typebuffer[option=TEX] \getbuffer
90
91Does it look better?
92
93\getbuffer[sample]
94
95Indeed it does, but watch this:
96
97\startbuffer[sample]
98\startitemize[packed,joinedup][rightmargin=8.5em]
99    \startitem
100        \samplefile{ward}\MyFill{DW}\par
101        \samplefile{ward}\par
102        \samplefile{ward}\MyFill{DW}
103    \stopitem
104\stopitemize
105\stopbuffer
106
107\typebuffer[sample][option=TEX]
108
109The first \type {\MyFill} will set the \type {\parfillskip} to a value that will
110also be used later on.
111
112\getbuffer[sample]
113
114The way out is the following
115
116\startbuffer
117\starttexdefinition MyFill #1
118    \begingroup
119    \parfillskip-1\rightskip plus 1fil\relax
120    \leaders
121        \ruledhbox to 1em{\hss.\hss}
122        \hfill
123    \ruledhbox{#1}
124    \par
125    \endgroup
126\stoptexdefinition
127\stopbuffer
128
129\typebuffer[option=TEX] \getbuffer
130
131This looks more or less okay. The \type {\par} keeps the adaption local but for
132it to work well, the \type {\par} must be inside the group.
133
134\getbuffer[sample]
135
136Now it's time to go for perfection! First of all, we get rid of any leading
137spacing. If we need some we should inject it after a cleanup. We also use a
138different leader command. Instead of \type {to} we use a \type {spread} so that
139we get half the emwidth and not something slightly less due to the width of the
140period.
141
142\startbuffer
143\starttexdefinition MyFill #1
144    \removeunwantedspaces
145    \begingroup
146    \parfillskip-1\rightskip plus 1fil\relax
147    \cleaders
148        \ruledhbox spread 1em{\hss.\hss}
149        \hfill
150    \ruledhbox{#1}
151    \par
152    \endgroup
153\stoptexdefinition
154\stopbuffer
155
156\typebuffer[option=TEX] \getbuffer
157
158So, we end up here:
159
160\startbuffer[sample]
161\startitemize[packed,joinedup][rightmargin=5em]
162    \startitem
163        \samplefile{sapolsky}\MyFill{RS}\par
164    \stopitem
165\stopitemize
166\stopbuffer
167
168\getbuffer[sample]
169
170For which we used this:
171
172\typebuffer[sample][option=TEX]
173
174Finally we get rid of the tracing:
175
176\startbuffer
177\starttexdefinition unexpanded MyFill #1
178    \begingroup
179    \parfillskip-1\rightskip plus 1fil\relax
180    \leaders
181        \hbox to \emwidth{\hss.\hss}
182        \hfill
183    \hbox{#1}
184    \par
185    \endgroup
186\stoptexdefinition
187\stopbuffer
188
189\typebuffer[option=TEX] \getbuffer
190
191Watch a few more details. It brings us to:
192
193\getbuffer[sample]
194
195\page
196
197\startbuffer
198\definefiller
199  [MyFiller]
200  [offset=.25\emwidth,
201   method=middle]
202
203\starttexdefinition unexpanded MyFill #1
204    \begingroup
205    \parfillskip-1\rightskip plus 1fil\relax
206    \filler[MyFiller]%
207    \hbox{#1}
208    \par
209    \endgroup
210\stoptexdefinition
211\stopbuffer
212
213\typebuffer[option=TEX] \getbuffer
214
215\getbuffer[sample]
216
217When writing these examples I realized that it's rather trivial to add this
218option to the already existing filler mechanism. The definition of such a filler
219looks like this:
220
221\startbuffer
222\definefiller
223  [MyFiller]
224  [offset=.25\emwidth,
225   rightmargindistance=-\rightskip,
226   method=middle]
227\stopbuffer
228
229\typebuffer[option=TEX] \getbuffer
230
231\startbuffer[sample]
232\startitemize[packed,joinedup][rightmargin=5em]
233    \startitem
234        \samplefile{sapolsky}\fillupto[MyFiller]{RS}
235    \stopitem
236\stopitemize
237\stopbuffer
238
239The sample code now becomes:
240
241\typebuffer[sample][option=TEX]
242
243Ans as expected renders as:
244
245\getbuffer[sample]
246
247\stopcomponent
248