summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/hybrid/hybrid-grouping.tex
blob: 44018e74633b4cb15c1ab649dd13d9a10555b93d (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
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
\startcomponent hybrid-grouping

\startbuffer[MyAbstract]
\StartAbstract
    In this article I will discuss a few things that are hard to do in
    traditional \TEX, but reasonable well in \LUATEX.
\StopAbstract
\stopbuffer

\doifmodeelse {tugboat} {
    \usemodule[tug-01,abr-01]
    \setvariables
      [tugboat]
      [columns=yes]
    \setvariables
      [tugboat]
      [year=2010,
       volume=99,
       number=9,
       page=99]
    \setvariables
      [tugboat]
      [title=Grouping,
       subtitle=A few things you can do with LUATEX,
       keywords=,
       author=Hans Hagen,
       address=PRAGMA ADE\\Ridderstraat 27\\8061GH Hasselt NL,
       email=pragma@wxs.nl]
    %
    % we use a buffer as abstract themselves are buffers and
    % inside macros we loose line endings and such
    \getbuffer[MyAbstract]
    %
    \StartArticle
} {
    \environment hybrid-environment
    \startchapter[title={Grouping}]
}

\setupbars[rulethickness=.15] % nicer

\startsection [title={Variants}]

After using \TEX\ for a while you get accustomed to one of its interesting
concepts: grouping. Programming languages like \PASCAL\ and \MODULA\ have
keywords \type {begin} and \type {end}. So, one can say:

\starttyping
if test then begin
    print_bold("test 1")
    print_bold("test 2")
end
\stoptyping

Other languages provide a syntax like:

\starttyping
if test {
    print_bold("test 1")
    print_bold("test 2")
}
\stoptyping

So, in those languages the \type {begin} and \type {end} and|/|or the curly
braces define a \quote {group} of statements. In \TEX\ on the other hand we have:

\starttyping
test \begingroup \bf test \endgroup test
\stoptyping

Here the second \type {test} comes out in a bold font and the switch to bold
(basically a different font is selected) is reverted after the group is closed.
So, in \TEX\ grouping deals with scope and not with grouping things together.

In other languages it depends on the language of locally defined variables are
visible afterwards but in \TEX\ they're really local unless a \type {\global}
prefix (or one of the shortcuts) is used.

In languages like \LUA\ we have constructs like:

\starttyping
for i=1,100 do
    local j = i + 20
    ...
end
\stoptyping

Here \type {j} is visible after the loop ends unless prefixed by \type {local}.
Yet another example is \METAPOST:

\starttyping
begingroup ;
    save n ; numeric n ; n := 10 ;
    ...
endgroup ;
\stoptyping

Here all variables are global unless they are explicitly saved inside a group.
This makes perfect sense as the resulting graphic also has a global (accumulated)
property. In practice one rarely needs grouping, contrary to \TEX\ where one
really wants to keep changes local, if only because document content is so
unpredictable that one never knows when some change in state happens.

In principle it is possible to carry over information across a group boundary.
Consider this somewhat unrealistic example:

\starttyping
\begingroup
    \leftskip 10pt
    \begingroup
        ....
        \advance\leftskip 10pt
        ....
    \endgroup
\endgroup
\stoptyping

How do we carry the advanced leftskip over the group boundary without using a
global assignment which could have more drastic side effects? Here is the trick:

\starttyping
\begingroup
    \leftskip 10pt
    \begingroup
        ....
        \advance\leftskip 10pt
        ....
        \expandafter
    \endgroup
    \expandafter \leftskip \the\leftskip
\endgroup
\stoptyping

This is typical the kind of code that gives new users the creeps but normally
they never have to do that kind of coding. Also, that kind of tricks assumes that
one knows how many groups are involved.

\stopsection

\startsection [title={Implication}]

What does this all have to do with \LUATEX\ and \MKIV ? The user interface of
\CONTEXT\ provide lots of commands like:

\starttyping
\setupthis[style=bold]
\setupthat[color=green]
\stoptyping

Most of them obey grouping. However, consider a situation where we use \LUA\ code
to deal with some aspect of typesetting, for instance numbering lines or adding
ornamental elements to the text. In \CONTEXT\ we flag such actions with
attributes and often the real action takes place a bit later, for instance when a
paragraph or page becomes available.

A comparable pure \TEX\ example is the following:

\starttyping
{test test \bf test \leftskip10pt test}
\stoptyping

Here the switch to bold happens as expected but no leftskip of 10pt is applied.
This is because the set value is already forgotten when the paragraph is actually
typeset. So in fact we'd need:

\starttyping
{test test \bf test \leftskip10pt test \par}
\stoptyping

Now, say that we have:

\starttyping
{test test test \setupflag[option=1] \flagnexttext test}
\stoptyping

We flag some text (using an attribute) and expect it to get a treatment where
option~1 is used. However, the real action might take place when \TEX\ deals with
the paragraph or page and by that time the specific option is already forgotten
or it might have gotten another value. So, the rather natural \TEX\ grouping does
not work out that well in a hybrid situation.

As the user interface assumes a consistent behaviour we cannot simply make these
settings global even if this makes much sense in practice. One solution is to
carry the information with the flagged text i.e.\ associate it somehow in the
attribute's value. Of course, as we never know in advance when this information
is used, this might result in quite some states being stored persistently.

A side effect of this \quote {problem} is that new commands might get suboptimal
user interfaces (especially inheritance or cloning of constructs) that are
somewhat driven by these \quote {limitations}. Of course we may wonder if the end
user will notice this.

To summarize this far, we have three sorts of grouping to deal with:

\startitemize[item]

\startitem
    \TEX's normal grouping model limits its scope to the local situation and
    normally has only direct and local consequences. We cannot carry information
    over groups.
\stopitem

\startitem
    Some of \TEX's properties are applied later, for instance when a paragraph or
    page is typeset and in order to make \quote {local} changes effective, the
    user needs to add explicit paragraph ending commands (like \type {\par} or
    \type {\page}).
\stopitem

\startitem
    Features dealt with asynchronously by \LUA\ are at that time unaware of
    grouping and variables set that were active at the time the feature was
    triggered so there we need to make sure that our settings travel with the
    feature. There is not much that a user can do about it as this kind of
    management has to be done by the feature itself.
\stopitem

\stopitemize

\stopsection

It is the third case that we will give an example of in the next section. We
leave it up to the user if it gets noticed on the user interface.

\startsection [title={An example}]

A group of commands that has been reimplemented using a hybrid solution is
underlining or more generic: bars. Just take a look at the following examples and
try to get an idea on how to deal with grouping. Keep in mind that:

\startitemize[packed]
\startitem
    Colors are attributes and are resolved in the backend, so way after the
    paragraph has been typeset.
\stopitem
\startitem
    Overstrike is also handled by an attribute and gets applied in the backend as
    well, before colors are applied.
\stopitem
\startitem
    Nested overstrikes might have different settings.
\stopitem
\startitem
    An overstrike rule either inherits from the text or has its own color
    setting.
\stopitem
\stopitemize

First an example where we inherit color from the text:

\startbuffer
\definecolor[myblue][b=.75]
\definebar[myoverstrike][overstrike][color=]

Test \myoverstrike{%
    Test \myoverstrike{\myblue
        Test \myoverstrike{Test}
        Test}
    Test}
Test
\stopbuffer

\typebuffer \getbuffer

Because color is also implemented using attributes and processed later on we can
access that information when we deal with the bar.

The following example has its own color setting:

\startbuffer
\definecolor[myblue][b=.75]
\definecolor[myred] [r=.75]
\definebar[myoverstrike][overstrike][color=myred]

Test \myoverstrike{%
    Test \myoverstrike{\myblue
        Test \myoverstrike{Test}
        Test}
    Test}
Test
\stopbuffer

\typebuffer \getbuffer

See how we can color the levels differently:

\startbuffer
\definecolor[myblue] [b=.75]
\definecolor[myred]  [r=.75]
\definecolor[mygreen][g=.75]

\definebar[myoverstrike:1][overstrike][color=myblue]
\definebar[myoverstrike:2][overstrike][color=myred]
\definebar[myoverstrike:3][overstrike][color=mygreen]

Test \myoverstrike{%
    Test \myoverstrike{%
        Test \myoverstrike{Test}
        Test}
    Test}
Test
\stopbuffer

\typebuffer \getbuffer

Watch this:

\startbuffer
\definecolor[myblue] [b=.75]
\definecolor[myred]  [r=.75]
\definecolor[mygreen][g=.75]

\definebar[myoverstrike][overstrike][max=1,dy=0,offset=.5]
\definebar[myoverstrike:1][myoverstrike][color=myblue]
\definebar[myoverstrike:2][myoverstrike][color=myred]
\definebar[myoverstrike:3][myoverstrike][color=mygreen]

Test \myoverstrike{%
    Test \myoverstrike{%
        Test \myoverstrike{Test}
        Test}
    Test}
Test
\stopbuffer

\typebuffer \getbuffer

It this the perfect user interface? Probably not, but at least it keeps the
implementation quite simple.

The behaviour of the \MKIV\ implementation is roughly the same as in \MKII,
although now we specify the dimensions and placement in terms of the ratio of the
x-height of the current font.

\startbuffer
Test \overstrike{Test \overstrike{Test \overstrike{Test} Test} Test} Test \blank
Test \underbar  {Test \underbar  {Test \underbar  {Test} Test} Test} Test \blank
Test \overbar   {Test \overbar   {Test \overbar   {Test} Test} Test} Test \blank
Test \underbar  {Test \overbar   {Test \overstrike{Test} Test} Test} Test \blank
\stopbuffer

\typebuffer \getbuffer

As an extra this mechanism can also provide simple backgrounds. The normal
background mechanism uses \METAPOST\ and the advantage is that we can use
arbitrary shapes but it also carries some limitations. When the development of
\LUATEX\ is a bit further along the road I will add the possibility to use
\METAPOST\ shapes in this mechanism.

Before we come to backgrounds, first take a look at these examples:

\startbuffer
\startbar[underbar]  \input zapf \stopbar \blank
\startbar[underbars] \input zapf \stopbar \blank
\stopbuffer

\typebuffer \getbuffer

First notice that it is no problem to span multiple lines and that hyphenation is
not influenced at all. Second you can see that continuous rules are also
possible. From such a continuous rule to a background is a small step:

\startbuffer
\definebar
  [backbar]
  [offset=1.5,rulethickness=2.8,color=blue,
   continue=yes,order=background]

\definebar
  [forebar]
  [offset=1.5,rulethickness=2.8,color=blue,
   continue=yes,order=foreground]
\stopbuffer

\typebuffer \getbuffer

The following example code looks messy but this has to do with the fact that we
want properly spaced sample injection.

\startbuffer
from here
    \startcolor[white]%
        \startbar[backbar]%
            \input zapf
            \removeunwantedspaces
        \stopbar
    \stopcolor
\space till here
\blank
from here
    \startbar[forebar]%
        \input zapf
        \removeunwantedspaces
    \stopbar
\space till here
\stopbuffer

\typebuffer \getbuffer

Watch how we can use the order to hide content. By default rules are drawn on top
of the text.

Nice effects can be accomplished with transparencies:

\startbuffer
\definecolor [tblue] [b=.5,t=.25,a=1]
\setupbars [backbar] [color=tblue]
\setupbars [forebar] [color=tblue]
\stopbuffer

\typebuffer \getbuffer

We use as example:

\startbuffer[sample]
from here {\white \backbar{test test}
    \backbar {nested nested} \backbar{also also}} till here
from here {\white \backbar{test test
    \backbar {nested nested}          also also}} till here
from here {\white \backbar{test test
    \backbar {nested nested}          also also}} till here
\stopbuffer

\typebuffer[sample] \getbuffer[sample]

The darker nested variant is just the result of two transparent bars on top of
each other. We can limit stacking, for instance:

\startbuffer
\setupbars[backbar][max=1]
\setupbars[forebar][max=1]
\stopbuffer

\typebuffer \getbuffer

This gives

\getbuffer[sample]

There are currently some limitations that are mostly due to the fact that we use
only one attribute for this feature and a change in value triggers another
handling. So, we have no real nesting here.

The default commands are defined as follows:

\starttyping
\definebar[overstrike]  [method=0,dy= 0.4,offset= 0.5]
\definebar[underbar]    [method=1,dy=-0.4,offset=-0.3]
\definebar[overbar]     [method=1,dy= 0.4,offset= 1.8]

\definebar[overstrikes] [overstrike] [continue=yes]
\definebar[underbars]   [underbar]   [continue=yes]
\definebar[overbars]    [overbar]    [continue=yes]
\stoptyping

As the implementation is rather non|-|intrusive you can use bars
almost everywhere. You can underbar a whole document but equally
well you can stick to fooling around with for instance formulas.

\startbuffer
\definecolor [tred]   [r=.5,t=.25,a=1]
\definecolor [tgreen] [g=.5,t=.25,a=1]
\definecolor [tblue]  [b=.5,t=.25,a=1]

\definebar [mathred]   [backbar] [color=tred]
\definebar [mathgreen] [backbar] [color=tgreen]
\definebar [mathblue]  [backbar] [color=tblue]

\startformula
    \mathred{e} = \mathgreen{\white mc} ^ {\mathblue{\white e}}
\stopformula
\stopbuffer

\typebuffer

We get:

\getbuffer

We started this chapter with some words on grouping. In the examples you see no
difference between adding bars and for instance applying color. However you need
to keep in mind that this is only because behind the screens we keep the current
settings along with the attribute. In practice this is only noticeable when you
do lots of (local) changes to the settings. Take:

\starttyping
{test test test \setupbars[color=red] \underbar{test} test}
\stoptyping

This results in a local change in settings, which in turn will associate a new
attribute to \type {\underbar}. So, in fact the following underbar becomes a
different one than previous underbars. When the page is prepared, the unique
attribute value will relate to those settings. Of course there are more
mechanisms where such associations take place.

\stopsection

\startsection [title={More to come}]

Is this all there is? No, as usual the underlying mechanisms can be used for
other purposes as well. Take for instance inline notes:

\startbuffer
According to the wikipedia this is the longest English word:
pneumonoultramicroscopicsilicovolcanoconiosis~\shiftup {other long
words are pseudopseudohypoparathyroidism and
flocci­nauci­nihili­pili­fication}. Of course in languages like Dutch and
German we can make arbitrary long words by pasting words together.
\stopbuffer

\typebuffer

This will produce:

\getbuffer

I wonder when users really start using such features.

\stopsection

\startsection [title={Summary}]

Although under the hood the \MKIV\ bar commands are quite different from their
\MKII\ counterparts users probably won't notice much difference at first sight.
However, the new implementation does not interfere with the par builder and other
mechanisms. Plus, it is configurable and it offers more functionality. However,
as it is processed rather delayed, side effects might occur that are not
foreseen.

So, if you ever notice such unexpected side effects, you know where it might
result from: what you asked for is processed much later and by then the
circumstances might have changed. If you suspect that it relates to grouping
there is a simple remedy: define a new bar command in the document preamble
instead of changing properties mid|-|document. After all, you are supposed to
separate rendering and content in the first place.

\stopsection

\doifmodeelse {tugboat} {
    \StopArticle
} {
    \stopchapter
}

\stopcomponent