summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/about/about-mathstackers.tex
blob: 07fadf102ae689cc2fc7bf002445a06c0e2da5ee (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
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
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
% language=uk

\startcomponent about-mathstackers

\environment about-environment

\startchapter[title=Math stackers]

\startsection[title=Introduction]

In the next sections I will discuss the way we deal with stacked content in
\CONTEXT\ \MKIV\ and in particular extensible characters. The mechanism describe
here is actually more generic and can also deal with regular text. The stacker
code is an evolution of the mechanisms that combine math arrows with text. From
the users perspective there is not that much difference with the old methods
because in practice \quote {defined} commands are used and their name stayed.
However, we use different definition and setup commands and provide much more
control. The new implementation is leaner but not meaner and fits the way \MKIV\
is set up.

How does \LUA\ fits in? We use a helper in order to determine some
characteristics of extensibles, but we could have done without. We also use some
new \LUATEX\ math primitives and of course we depend on \OPENTYPE\ font
technoloygy.

\stopsection

\startsection[title=Extensibles]

The command \type {\leftarrowfill} was introduced in plain \TEX\ and gives, as
the name indicates, a \leftarrowfill\ that stretches itself so that it takes the
available space. Take the following example:

\starttyping
\hbox to 4cm{\leftarrowfill}
\stoptyping

This will make an arrow of length 4cm:

\blank \mathstylehbox{\Umathaccent\fam\zerocount"2190{\hskip4cm}} \blank

This arrow is made out of small snippets:

\blank {\showglyphs\scale[width=\textwidth]{\mathstylehbox{\Umathaccent\fam\zerocount"2190{\hskip4cm}}}} \blank

Here is another one:

\starttyping
\hbox to 4cm{\rightoverleftarrowfill}
\stoptyping

or:

\blank {\mathstylehbox{\Umathaccent\fam\zerocount"21C4{\hskip4cm}}} \blank

This time we have three different snippets:

\blank {\showglyphs\scale[width=\textwidth]{\mathstylehbox{\Umathaccent\fam\zerocount"21C4{\hskip4cm}}}} \blank

The \TEX\ engine has a concept of extensible characters. In fact there are two
mechanisms: there is a list of larger glyphs and when that list is exhausted
larger characters can be constructed out of snippets. Examples are left and right
fences in math like braces and brackets, and, also in math, some top and bottom
accents.

For reasons unknown to me, some of these extensibles are handled by the engine
directly, using properties of a font, while others are composed using macros.
Given that \TEX\ is quite popular for typesetting scientific articles it is
beyond my understanding why no one decided to provide some more fonts and|/|or
extend the \TEX\ engine. After all, the whole idea of Donald Knuth with \TEX\ was
that it could be adapted to future needs by its users. And so, more that 30 years
after \TEX\ and macro packages showed up we're stuck with not only incomplete
fonts, but also an engine that was never adapted to demands.

\stopsection

\startsection[title=The traditional way]

In \CONTEXT\ we have support for extensibles built into the core but it uses the
traditional approach: take some snippets and paste them together, making sure to
achieve some overlap and get rid of side bearings. In terms of \TEX\ code this can
best be illustrated with the plain \TEX\ definition of such a command:

\starttyping
\def\leftarrowfill
  {$%
   \mathsurround0pt%
   \mathord\leftarrow\mkern-7mu%
   \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
   \mkern-7mu\smash-%
   $}
\stoptyping

Here we create a tight formula starting with a \type {leftarrow}, ending with a
minus sign and glued together with the number of minus signs that are needed to
fill the available space. This macro eventually expands to something like this (a
bit spaced out):

\starttyping
\def\leftarrowfill { $
  % \leftarrow = \mathchardef\leftarrow="3220 in plain but in
  % unicode it's character 0x2190 so we use that one here
  \mathsurround=0pt
  \mathord{\mathchar"2190}
  \mkern-7mu
  \cleaders
   \hbox { $
     \mkern-2mu
     \mathchoice
      {\setbox0\hbox{$\displaystyle     -$}\ht0=0pt\dp0=0pt\box0}
      {\setbox0\hbox{$\textstyle        -$}\ht0=0pt\dp0=0pt\box0}
      {\setbox0\hbox{$\scriptstyle      -$}\ht0=0pt\dp0=0pt\box0}
      {\setbox0\hbox{$\scriptscriptstyle-$}\ht0=0pt\dp0=0pt\box0}
     \mkern-2mu
    $ }
   \hfill
  \mkern-7mu
  \mathchoice
   {\setbox0\hbox{$\displaystyle     -$}\ht0=0pt\dp0=0pt\box0}
   {\setbox0\hbox{$\textstyle        -$}\ht0=0pt\dp0=0pt\box0}
   {\setbox0\hbox{$\scriptstyle      -$}\ht0=0pt\dp0=0pt\box0}
   {\setbox0\hbox{$\scriptscriptstyle-$}\ht0=0pt\dp0=0pt\box0}
$ }
\stoptyping

If you look at the code you see a few hacks. First of all we see that we need to
add kerns in order to make the symbols overlap. For the middle shapes this is
understandable as there we don't want rounding errors to lead to gaps. Also,
because the minus in Computer Modern (and therefore Latin Modern) has rounded
tips, we need to make sure that we end up beyond the tips. Next we see two blobs
of \type {mathchoice}. This primitive chooses one of the four variants and
switches to the right math style. It packages the minus and smashes it. In our
case smashing makes not much sense as the arrowhead has height and depth anyway,
but it's a side effect of using general purpose macros that there can be some
unneeded overhead.

\blank
\hbox \bgroup \quad
    \scale[sx=5,sy=5]{\hbox{\showglyphs$\mathsurround\zeropoint\char"2190$}}\quad
    \scale[sx=5,sy=5]{\hbox{\showglyphs$\mathsurround\zeropoint\char"002D$}}\quad
    \scale[sx=5,sy=5]{\hbox{\showglyphs$\mathsurround\zeropoint\char"27F8$}}\quad
    \scale[sx=5,sy=5]{\hbox{\showglyphs$\mathsurround\zeropoint\char"003D$}}\quad
\egroup
\blank

Above you see the two characters that traditionally are combined into a leftward
pointing arrows. Watch the whitespace on the left and right of the actual glyph.

\stopsection

\startsection[title=The new way]

These zero height and depth don't show up in our rendered examples. Why is this?
The reason is that I cheated a bit. I used this to get the arrow: \footnote {In
this example I misuse the accent placement mechanism. Upto \LUATEX\ 0.75 that was
the way to go.}

\starttyping
\mathstylehbox{\Umathaccent\fam\zerocount"21C4{\hskip4cm}}
\stoptyping

The \CONTEXT\ support macro \type {\mathstylehbox} is an efficient variant of
\type {\mathchoice}. More significant is that we don't assemble the arrow, but
just put it as an accent on top of a skip. The \type {\Umathaccent} primitive
will assemble the long arrow for us, using information in the font. If we look
into the definition of the (Latin Modern) font in \MKIV\ we see this:

\starttyping
[8592]={
 ["boundingbox"]={ 57, -10, 942, 510 },
 ["class"]="base",
 ["index"]=1852,
 ["math"]={
  ["horiz_parts"]={
   {
    ["advance"]=507,
    ["end"]=169,
    ["extender"]=0,
    ["glyph"]=984274,
    ["start"]=0,
   },
   {
    ["advance"]=337,
    ["end"]=337,
    ["extender"]=1,
    ["glyph"]=984275,
    ["start"]=337,
   },
   {
    ["advance"]=507,
    ["end"]=0,
    ["extender"]=0,
    ["glyph"]=984276,
    ["start"]=169,
   },
  },
  ["horiz_variants"]={ 10229 },
 },
 ["name"]="arrowleft",
 ["width"]=1000,
}
\stoptyping

This arrow symbol comes in two sizes. The extra size is mentioned in \type
{horiz_variants}. When no more variants are seen, it switches to the extensible
definition, that uses \type {horiz_parts}. The dimensions are in basepoints, the
references to glyphs are decimal. The \type {end} and \type {start} fields
specify the overlap. When \type {extender} equals 1 it signals a repeatable
snippet.

In the \TEX\ engine the slot allocated for the left arrow symbol has a \type
{next} pointer to a larger shape. Here there is only one such shape but when
there are more they form a linked list. The the last one in such a list gets the
specification of the extenders.

We hard|-|coded the width to 4cm so how does it work when the arrow has to adapt
itself? There are two cases there. When we are putting text on top of or below an
arrow, we know what the width is because we can measure the text. But when we use
the arrow as a filler, we have to leave it to the engine to arrange it. In recent
\LUATEX\ the definition can be as simple as:

\starttyping
\def\leftarrowfill{\leaders "2190 \hfill}
\stoptyping

or:

\starttyping
\def\leftarrowfill{\mathstylehbox{\leaders"2190\hfill}}
\stoptyping

In fact, we can use this new \LUATEX\ extension to \type {\leaders} to
replace the accent hacks as well.

\stopsection

\startsection[title=Wrapping it in macros]

If this was all, we would be done in a few lines of definitions but as usual
there is more involved: especially text. The prerequisites can be summarized as
follows:

\startitemize[packed]
\startitem
    The width of the extensible need to adapt itself automatically.
\stopitem
\startitem
    We need to be able to control horizontal and vertical offsets.
\stopitem
\startitem
    We best have a math as well as a text variant (which is handy for chemistry).
\stopitem
\startitem
    For historic reasons we need to deal with optional arguments in a special
    (reverse) way.
\stopitem
\startitem
    We need alternatives for extensibles on top, in the middle and at the bottom.
\stopitem
\stopitemize

Using a low level command we can do this:

\startbuffer[math]
$x \directmathextensible{"2192}{top}{bottom} x$
\stopbuffer

\typebuffer[math] \blank \getbuffer[math] \blank

This is not that exiting too look at, but the next might be:

\enabletrackers[math.stackers.texts]

\blank \getbuffer[math] \blank

Here we have turned on a tracker:

\starttyping
\enabletrackers[math.stackers.texts]
\stoptyping

The toppart is transparent blue, the middlepart transparent red and the bottom
part becomes transparent green. When the areas overlap you see the mixed color.

Before we explore some options, we show some variants. Often extensibles are used
in math mode, if only because they originate in math and come from math fonts.

\startbuffer[text]
$x \textstacker{"2192}{top}{bottom} x$
\stopbuffer

\typebuffer[text] \blank \getbuffer[text] \blank

These commands also work outside math mode:

\startbuffer[none]
x \textstacker{"2192}{top}{bottom} x
\stopbuffer

\typebuffer[none] \blank \getbuffer[none] \blank

and to some extend can adapt themselves:

\startbuffer[high]
x\high{x \textstacker{"2192}{top}{bottom} x} x
\stopbuffer

\typebuffer[high] \blank[2*big] \getbuffer[high] \blank

\stopsection

\startsection[title=Influencing the spacing]

We will use the text example to illustrate some options.

\startbuffer[demo]
\ruledhbox \bgroup \quad
    \setupmathstackers[location=top]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[location=high]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[location=middle]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[location=low]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[location=bottom]%
    \textstacker{"21C4}{top}{bottom}\quad
\egroup
\stopbuffer

\typebuffer[demo]

You can set up extensibles to be shifted up and down.

\blank \getbuffer[demo] \blank

The above rendering uses the default spacing. When we set all values to zero we
get this:

\startbuffer[setup]
\setupmathstackers
  [voffset=\zeropoint,
   hoffset=\zeropoint,
   minheight=\exheight,
   mindepth=\zeropoint,
   minwidth=\zeropoint]
\stopbuffer

\blank \start \getbuffer[setup,demo] \stop \blank

The setup looks like this:

\typebuffer[setup]

and gives a pretty tight rendering. The default values are:

\starttyping
\setupmathstackers
  [voffset=.25\exheight,
   hoffset=.5\emwidth,
   minheight=\exheight,
   mindepth=\zeropoint,
   minwidth=\emwidth]
\stoptyping

\startbuffer[setup]
\setupmathstackers
  [voffset=2\exheight,
   hoffset=\emwidth,
   minheight=\exheight,
   mindepth=\zeropoint,
   minwidth=\zeropoint]
\stopbuffer

When we set \type {voffset} to twice the ex|-|height and \type {hoffset} to
the em|-|width we get:

\blank \start \getbuffer[setup,demo] \stop \blank

We can enforce a (consistent) height and depth of the extensible by setting the
minimum values:

\startbuffer[setup]
\setupmathstackers
  [voffset=\zeropoint,
   hoffset=\zeropoint,
   minheight=5\exheight,
   mindepth=3\exheight,
   minwidth=6\emwidth]
\stopbuffer

\typebuffer

\blank \start \getbuffer[setup,demo] \stop \blank

\stopsection

\startsection[title=A neat feature]

A more obscure feature relates to the visual appearance. When we put something
on top of for instance an arrow, it sometimes looks better when we only consider
the middle part. Watch the following:

\startbuffer[setup]
\setupmathstackers
  [voffset=\zeropoint,
   hoffset=\zeropoint,
   minheight=\zeropoint,
   mindepth=\zeropoint,
   minwidth=\zeropoint]
\stopbuffer

\startbuffer[demo]
\ruledhbox \bgroup \quad
    \setupmathstackers[offset=normal]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[offset=min]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[offset=max]%
    \textstacker{"21C4}{top}{bottom}\quad
\egroup
\stopbuffer

\typebuffer[demo]

The \type {min} and \type {max} values will add extra offsets that relate to the
width of the edge snippets.

\blank \start \getbuffer[setup,demo] \stop \blank

In this case both have the same result but the difference becomes clear when we
set the \type {hoffset} to the em|-|width. In the case of \type {min} we don't
add some extra space if the \type {hoffset} is applied.

\startbuffer[setup]
\setupmathstackers
  [voffset=\zeropoint,
   hoffset=\emwidth,
   minheight=\zeropoint,
   mindepth=\zeropoint,
   minwidth=\zeropoint]
\stopbuffer

\startbuffer[demo]
\ruledhbox \bgroup \quad
    \setupmathstackers[offset=normal]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[offset=min]%
    \textstacker{"21C4}{top}{bottom}\quad
    \setupmathstackers[offset=max]%
    \textstacker{"21C4}{top}{bottom}\quad
\egroup
\stopbuffer

\typebuffer[demo]

Of course in this example we have a symmetrical correction.

\blank \start \getbuffer[setup,demo] \stop \blank

A one sided arrow behaves different:

\startbuffer[demo]
\ruledhbox \bgroup \quad
    \setupmathstackers[offset=normal]%
    \textstacker{"2192}{top}{bottom}\quad
    \setupmathstackers[offset=min]%
    \textstacker{"2192}{top}{bottom}\quad
    \setupmathstackers[offset=max]%
    \textstacker{"2192}{top}{bottom}\quad
\egroup
\stopbuffer

\blank \start \getbuffer[setup,demo] \stop \blank

\stopsection

\startsection[title=The user interface]

It all starts out with categories. We have a couple of predefined categories in
the core. The \type {mathematics} category typesets the top and bottom texts in
mathmode, while the \type {text} category doesn't. The \type {reverse} category
swaps its arguments. There are \type {upper} and \type {under} categories too.

As with most \CONTEXT\ mechanisms inheritance is part of the picture:

\starttyping
\definemathextensibles [mine] [big] [offset=min]
\stoptyping

You can change settings with:

\starttyping
\setupmathstackers [mine] [big] [voffset=\exheight]
\stoptyping

For downward compatibility we also provide these:

\starttyping
\definemathextensibles [normal] [hoffset=0.5\emwidth]
\definemathextensibles [none]   [hoffset=\zeropoint]
\definemathextensibles [small]  [hoffset=1\emwidth]
\definemathextensibles [medium] [hoffset=1.5\emwidth]
\definemathextensibles [big]    [hoffset=2\emwidth]
\stoptyping

They inherit from \type {mathematics} so choosing this also forces the top and
bottomtexts to be typeset in math mode.

These commands don't define extensibles, they only provide a way to categorize
them. There are couple of definers and one reason for that is that we want to
define downward compatible commands.

\starttyping
\definemathextensible [reverse] [xleftarrow]  ["2190]
\definemathextensible [reverse] [xrightarrow] ["2192]
\stoptyping

The \type {x} in the name is sort of standard for an extensible symbol with
optionally some text on top or below. The reverse forced compatible behaviour.

\startbuffer
\xrightarrow{stuff below} {stuff on top} \quad
\xrightarrow{stuff on top}               \quad
\xrightarrow{}            {stuff on top} \quad
\xrightarrow{stuff below} {}             \quad
\xrightarrow{}            {}             \quad
\xrightarrow                             \quad
\stopbuffer

\typebuffer \getbuffer

New in \MKIV\ is the \type {t} variant that typesets the text as (indeed) text.
In addition we have a normal|-|order \type {m} variant:

\starttyping
\definemathextensible [text] [tleftarrow]  ["2190]
\definemathextensible [text] [trightarrow] ["2192]

\definemathextensible [mathematics] [mleftarrow]  ["2190]
\definemathextensible [mathematics] [mrightarrow] ["2192]
\stoptyping

This time the order is always top first and bottom next:

\startbuffer
\trightarrow{stuff on top} {stuff below} \quad
\trightarrow{stuff on top} {}            \quad
\trightarrow{stuff on top}               \quad
\trightarrow{}             {stuff below} \quad
\trightarrow                             \quad
\stopbuffer

\typebuffer

So we get:

\getbuffer

As you can see, there is an optional first argument that specifies the category
that applies. This permits you to define extra commands that have their own
(spacing) properties.

Earlier on we saw that defined commands can be forced into a category:

\startbuffer
\trightarrow[big]   {stuff on top} {stuff below} \quad
\trightarrow[medium]{stuff on top} {stuff below} \quad
\trightarrow[small] {stuff on top} {stuff below}
\stopbuffer

\typebuffer

Here we get:

\getbuffer

A variation on this kind of extensibles are over- and underarrows. This time the
text is the nucleus.

\starttyping
\definemathoverextensible  [top]    [overleftarrow]   ["2190]
\definemathoverextensible  [top]    [overrightarrow]  ["2192]

\definemathunderextensible [bottom] [underleftarrow]  ["2190]
\definemathunderextensible [bottom] [underrightarrow] ["2192]
\stoptyping

In action this looks like:

\startbuffer
\ruledhbox \bgroup $ \quad
     \overleftarrow {a}  \quad    \overleftarrow {ABC}  $ \quad
  x_{\overleftarrow {a}} \quad x_{\overleftarrow {ABC}} $ \quad
     \underleftarrow{a}  \quad    \underleftarrow{ABC}  $ \quad
  x_{\underleftarrow{a}} \quad x_{\underleftarrow{ABC}} $ \quad
$ \egroup
\stopbuffer

\typebuffer

Here we also have tracing enabled, and we also show the bounding box:

\blank \getbuffer \blank

This leaves us one command: the one that defines the basic filler:

\starttyping
\definemathextensiblefiller [leftarrowfill]  ["2190]
\definemathextensiblefiller [rightarrowfill] ["2192]
\stoptyping

Commands defined like this will stretch themselves to fit the circumstances,
and normally they will fill op the available space.

\startbuffer
\hbox to 4cm {from here \leftarrowfill\ to there}
\hbox to 8cm {from there \rightarrowfill\ to here}
\stopbuffer

\typebuffer

These commands (like the others) work in text mode as well as in math mode.

\blank \getbuffer \blank

\stopsection

\startsection[title=Special cases]

One of the reasons why the arrows mechanism has always been somewhat
configureable is that we need arrows in the chemistry code.

\starttyping
\definemathextensibles
  [chemistry]
  [offset=max,
   left=\enspace,
   right=\enspace,
   hoffset=.5\emwidth]

\definemathextensible [chemistry] [cleftarrow]          ["2190]
\definemathextensible [chemistry] [crightarrow]         ["2192]
\definemathextensible [chemistry] [crightoverleftarrow] ["21C4]
\stoptyping

\startbuffer
2H + O \crightarrow{explosive}\ H\low{2}O
\stopbuffer

\typebuffer

Of course normally such code is wrapped into the chemistry enviroments and
support macros.

\blank \getbuffer \blank

If you want something else than an extensible you can use definitions like the
following:

\startbuffer
\definemathtriplet [tripleta]
\definemathtriplet [text] [tripletb]
\definemathtriplet [text] [tripletc] [\otimes]
\stopbuffer

\typebuffer \getbuffer

\startbuffer
\tripleta{\ominus}{top}{botom} and
\tripletb{\oplus} {top}{botom} and
\tripletc         {top}{botom}
\stopbuffer

\typebuffer

\blank \hbox{\getbuffer} \blank

As optional first argument you can pass a category.

\startbuffer
\tripleta[mathematics]{\ominus}{top}{botom} and
\tripletb[mathematics]{\oplus}{top}{botom} and
\tripletc[mathematics]{top}{botom}
\stopbuffer

\typebuffer

Which gives:

\blank \hbox{\getbuffer} \blank

Instead of \type {mathematics} you could have given its synonym \type {math}.
Keep in mind that categories are shared among stackers. There is also a direct
command:

\starttyping
before \mathtriplet{\otimes}{top}{botom} after
\stoptyping

\stopsection

\startsection[title=An overview]

We end with showing a list of extensibles that come with the font used here, the
\TEX Gyre Pagella. First we load a module:

\startbuffer
\usemodule[s][math-extensibles]
\stopbuffer

\typebuffer \getbuffer

This module provides a couple of commands that typesets a table with the
extensibles as known in \CONTEXT. Beware: not all fonts have all those
characters.

\startbuffer
\showmathextensibles[alternative=a]
\stopbuffer

A second command is:

\typebuffer

This commands shows the base glyph, and the stretched variant with text on top
and below. When no symbol is found in the font a rule is rendered.

\getbuffer

\startbuffer
\showmathextensibles[alternative=b]
\stopbuffer

\typebuffer

This command typesets a list with \UNICODE\ entries and defined commands. There
are empty entries due to lack of glyphs in the used font. Not all characters have
an associated command. Some have multiple commands with different math classes.

\getbuffer

\stopsection

\startsection[title=Remark]

The number of extensions to the \LUATEX\ core math engine is not that large and
mostly involves more control over spacing and support for \UNICODE\ math as
\OPENTYPE\ math extensibles. However, a few years after writing this chapter the
machinery was cleaned up a bit and in the process some more control was added to
constructors for radicals, fractions and delimiters. The spacing and composition
can be controlled in a bit more detail using keywords (and dimensions). Because
in \CONTEXT\ we already have mechanisms in place not much of that new
functionality is used (yet). Also, in the meantime \CONTEXT\ evolved further.
This chapter is just a snapshot and it might even render a bit different in more
recent versions of \CONTEXT\ and|/|or \LUATEX. After all, it was written as part
of the development story.

\stopsection

\stopchapter

\disabletrackers[math.extensibles.texts]

\stopcomponent