math-fen.mkxl /size: 51 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=math-fen,
3%D        version=2012.02.18,
4%D          title=\CONTEXT\ Math Macros,
5%D       subtitle=Fences,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Math Macros / Fences}
15
16\unprotect
17
18% \definemathfence [fancybracket] [bracket] [define=yes,color=blue]
19%
20% test $|x|$ test \par
21% test $||x||$ test (okay) \par
22% test $a\left|\frac{1}{b}\right|c$ test \par
23% test $a\left||\frac{1}{b}\right||c$ test (not okay) \par
24%
25% \setupmathfences [color=red]
26%
27% test $a\fenced[bar]{\frac{1}{b}}c$ test \par
28% test $a\fenced[doublebar]{\frac{1}{b}}c$ test \par
29% test $a\fenced[bracket]{\frac{1}{b}}c$ test \par
30% test $a\fancybracket{\frac{1}{b}}c$ test \par
31
32\installcorenamespace{mathfences}
33
34\installcommandhandler \??mathfences {mathfence} \??mathfences
35
36\aliased\let\setupmathfences\setupmathfence
37
38\setupmathfences
39  [\c!method=, % maybe always \v!auto
40   \c!left=,
41   \c!right=,
42   \c!middle=,
43   \c!mathstyle=,
44   \c!color=,
45   \c!symbolcolor=\mathfenceparameter\c!color,
46   \c!textcolor=\mathfenceparameter\c!color,
47   \c!leftcolor=\mathfenceparameter\c!symbolcolor,
48   \c!middlecolor=\mathfenceparameter\c!symbolcolor,
49   \c!rightcolor=\mathfenceparameter\c!symbolcolor,
50   \c!define=, % was \c!command
51   \c!mathclass=,
52   \c!leftclass=\mathopencode,
53   \c!rightclass=\mathclosecode,
54   \c!middleclass=\mathmiddlecode,
55   \c!leftsource=\zerocount,
56   \c!middlesource=\zerocount,
57   \c!rightsource=\mathfenceparameter\c!source,
58   \c!source=\zerocount,
59   \c!height=\zeropoint,
60   \c!depth=\zeropoint,
61   \c!distance=\zerocount,
62   \c!topspace=\zeropoint,
63   \c!bottomspace=\zeropoint,
64 % \c!overflow=\v!no,
65   \c!overflow=\v!auto,
66   \c!alternative=\v!big,
67   \c!factor=\v!auto,
68   \c!snap=\mathematicsparameter\c!snap] % "28
69
70\appendtoks
71    \ifcstok{\mathfenceparameter\c!define}\v!yes
72        \protected\edefcsname\currentmathfence\endcsname{\math_fenced_fenced{\currentmathfence}}%
73    \fi
74\to \everydefinemathfence
75
76%D So we can do:
77%D
78%D \starttyping
79%D $ a + \fenced[bar][size=1]   {\frac {b} {c}} + d $
80%D $ a + \fenced[bar][size=2]   {\frac {b} {c}} + d $
81%D $ a + \fenced[bar][size=3]   {\frac {b} {c}} + d $
82%D $ a + \fenced[bar][size=4]   {\frac {b} {c}} + d $
83%D $ a + \fenced[bar][size=big] {\frac {b} {c}} + d $
84%D $ a + \fenced[bar][size=Big] {\frac {b} {c}} + d $
85%D $ a + \fenced[bar][size=bigg]{\frac {b} {c}} + d $
86%D $ a + \fenced[bar][size=Bigg]{\frac {b} {c}} + d $
87%D $ a + \fenced[bar][factor=1] {\frac {b} {c}} + d $
88%D $ a + \fenced[bar][factor=2] {\frac {b} {c}} + d $
89%D $ a + \fenced[bar][factor=4] {\frac {b} {c}} + d $
90%D $ a + \fenced[bar]           {\frac {b} {c}} + d $
91%D \stoptyping
92
93% \startbuffer
94%     $ \left( \frac{1}{x}^{2} \right)$
95%     $ \left( x \right)$
96%     $ \left( x^2 \right)$
97%     $ \left( \frac{1}{x} \right)$
98%     $ \left( \frac{1}{x}^2 \right)$
99% \stopbuffer
100%
101% \getbuffer\blank
102% {\setupmathfence[topspace=-2pt,bottomspace=-1pt]\getbuffer\blank}
103
104% todo : class -> number
105
106\newconditional\c_math_fenced_mirror \c_math_fenced_mirror\conditionaltrue
107\newconditional\c_math_fenced_sized  \c_math_fenced_sized \conditionalfalse
108\newinteger    \c_math_fence_nesting
109
110\installcorenamespace {mathfencesize}
111
112\defcsname\??mathfencesize  big\endcsname{1}
113\defcsname\??mathfencesize  Big\endcsname{2}
114\defcsname\??mathfencesize bigg\endcsname{3}
115\defcsname\??mathfencesize Bigg\endcsname{4}
116
117\let\math_fenced_trace\donothing
118
119\def\math_fenced_common_factor_none % a weird one anyway
120  {\Uvextensible
121   \s!axis    \relaxedspace
122   \s!exact   \relaxedspace
123   \s!variant \mathvariantslot\fam \c_math_fence_nesting}
124 % \s!variant \mathvariantslot\fam {\c_math_fence_nesting+\plusone}}
125
126\def\math_fenced_common_factor_fixed
127  {\Uvextensible
128   \s!axis
129   \s!exact}
130
131\def\math_fenced_common_factor_unknown
132  {\scratchdimen{\p_factor\bodyfontsize/2}%
133   \Uvextensible
134   \s!height\scratchdimen
135   \s!depth \scratchdimen
136   \s!axis
137   \s!exact}
138
139\def\math_fenced_common_factor_force
140  {\Uvextensible
141   \s!height{\mathfenceparameter\c!height}%
142   \s!depth {\mathfenceparameter\c!depth}%
143   \s!axis
144   \s!exact}
145
146\def\math_fenced_common_factor_size
147  {\Uvextensible
148   \math_fenced_set_variant}
149
150\def\math_fenced_common_factor_empty#1%
151  {\ifconditional\c_math_fenced_level_mode
152     \Uvextensible
153   \else
154     #1% \Uleft \Umiddle \Uleft
155     \ifx#1\Umiddle
156       \ifx\p_overflow\v!auto
157         \s!middle\relaxedspace
158         \s!nooverflow\relaxedspace
159       \orelse\ifx\p_overflow\v!no
160         \s!nooverflow\relaxedspace
161       \fi
162     \fi
163   \fi}
164
165\def\math_fenced_common_factor_auto#1%
166  {\ifconditional\c_math_fenced_level_mode
167     \Uvextensible
168     \math_fenced_set_variant
169   \else
170     #1% \Uleft \Umiddle \Uleft
171     \math_fenced_set_variant
172     \ifx#1\Umiddle
173       \ifx\p_overflow\v!auto
174         \s!middle\relaxedspace
175         \s!nooverflow\relaxedspace
176       \orelse\ifx\p_overflow\v!no
177         \s!nooverflow\relaxedspace
178       \fi
179     \fi
180   \fi}
181
182% \startTEXpage[offset=1dk]
183%     \dm { \fenced[brace][middle="7C] { \frac{p}{q} \fence p,q \in \naturalnumbers} }\par
184%     \dm { \fenced[brace][middle=`|]  { \frac{p}{q} \fence p,q \in \naturalnumbers} }\par
185%     \dm { \fenced[brace][middle=124] { \frac{p}{q} \fence p,q \in \naturalnumbers} }\par
186%     \dm { \fenced[brace][middle=|]   { \frac{p}{q} \fence p,q \in \naturalnumbers} }
187% \stopTEXpage
188
189\newconstant\c_math_fenced_class
190\newinteger \c_math_fence_check
191
192\integerdef\c_math_factor_fenced\zerocount
193
194\installglobalmacrostack\c_math_factor_fenced
195
196\protected\def\math_fenced_common#1#2#3#4#5% \Uwhatever class symbol source color
197  {\c_math_fenced_class\math_class_by_parameter\mathfenceparameter#2%
198   \math_fenced_check_size_mismatch % we need to catch an unbalanced \F as we are sequential
199   \ifconditional\c_math_fenced_sized
200   \orelse\ifconditional\c_math_fenced_level_mode
201     \ifnum\c_math_fenced_class=\mathopencode
202       \integerdef\c_math_fenced_stack\c_math_fenced_level
203       \push_macro_c_math_fenced_stack
204     \orelse\ifnum\c_math_fenced_class=\mathclosecode
205       \pop_macro_c_math_fenced_stack
206       \c_math_fenced_level\c_math_fenced_stack
207     \fi
208   \fi
209   \edef\p_fence{#3}%
210   \ifempty\p_fence
211     \ifnum\c_math_fenced_class=\mathmiddlecode\else#1.\relax\fi
212   \else
213     %
214     \ifx\p_fence\v!none
215       \lettonothing\p_mp
216     \orelse\ifcstok{\mathfenceparameter\c!plugin}\v!mp
217       \edef\p_mp{\mathfenceparameter\c!mp}%
218       \ifempty\p_mp\else
219         \clf_set_extensible_data
220             mp      {\p_mp}
221             unicode \ifchknumber\p_fence\or\lastchknumber\else\expandafter`\p_fence\fi
222         \relax
223         % much of below is not relevant
224       \fi
225     \else
226       \lettonothing\p_mp
227     \fi
228     %
229     \edef\p_factor   {\mathfenceparameter\c!factor}%
230     \edef\p_overflow {\mathfenceparameter\c!overflow}%
231     \edef\p_size     {\mathfenceparameter\c!size}%
232     \edef\p_mathclass{\mathfenceparameter\c!mathclass}%
233     \edef\p_inline_factor{\ifconditional\indisplaymath\mathfenceparameter\c!displayfactor\else\mathfenceparameter\c!inlinefactor\fi}%
234     \scratchcounter\math_tags_mfunctionlabattribute\plusthree{\currentglobalmathfence}{\mathfenceparameter\c!mathmeaning}\relax
235     \ifempty\p_inline_factor
236       % nothing
237     \orelse\ifx#1\Uleft
238       \push_macro_c_math_factor_fenced
239       \integerdef\c_math_factor_fenced\p_inline_factor\relax
240     \orelse\ifx#1\Uright
241       \pop_macro_c_math_factor_fenced
242     \fi
243     \ifnum\c_math_fenced_level>\zerocount
244       \math_fenced_common_factor_fixed
245       \math_fenced_set_variant
246     \orelse\ifconditional\c_math_fenced_sized
247       \math_fenced_common_factor_fixed
248     \orelse\ifempty\p_factor
249       \math_fenced_common_factor_empty#1%
250     \orelse\ifx\p_factor\v!auto
251       \math_fenced_common_factor_auto#1%
252     \orelse\ifx\p_factor\v!none
253       \math_fenced_common_factor_none
254     \orelse\ifx\p_factor\v!fixed
255       \math_fenced_common_factor_fixed
256     \orelse\ifx\p_factor\v!force
257       \math_fenced_common_factor_force
258     \orelse\ifx\p_factor\v!size
259       \math_fenced_common_factor_size
260     \else
261       \math_fenced_common_factor_unknown
262     \fi
263     \usedsymbolcolorparameterattributes{\mathfenceparameter#5}%
264     \ifcase\scratchcounter\else
265       \s!attr \mathcategoryattribute \scratchcounter % will change
266     \fi
267     \s!class
268       \ifx\p_fence\v!none
269         \mathghostcode
270       \orelse\ifempty\p_mathclass
271         \c_math_fenced_class
272       \else
273         \mathcodechecked\p_mathclass
274       \fi
275     \s!source {\namedboxanchor{\mathfenceparameter#4}}%
276     %
277     \ifempty\p_mp\else
278       \s!usecallback\relaxedspace
279     \fi
280     %
281     \s!top    \mathfenceparameter\c!topspace
282     \s!bottom \mathfenceparameter\c!bottomspace
283     %
284     \ifzero\c_math_factor_fenced\else
285       \s!factor \c_math_factor_fenced
286     \fi
287     %
288     \ifcstok{\mathfenceparameter\c!snap}\v!yes
289       \s!single\relaxedspace
290     \fi
291     %
292     \math_fenced_trace
293     \ifx\p_fence\v!none
294     % todo: test with \nomathchar
295       \Umathchar\mathghostcode\fam\zerocount
296     \orelse\ifchknumber\p_fence\or
297       \Umathchar\mathghostcode\fam\lastchknumber
298     \else
299       \p_fence
300     \fi
301   \fi}
302
303\def\math_fenced_set_variant
304  {\ifconditional\c_math_fenced_level_mode
305     \s!variant \mathvariantslot\fam \c_math_fenced_level
306   \orelse\ifempty\p_size
307     % nothing
308   \orelse\ifcsname\??mathfencesize\p_size\endcsname
309     \s!variant \mathvariantslot\fam \numexpr\lastnamedcs\relax
310   \orelse\ifcstok{\mathfenceparameter\c!alternative}\v!big
311     \s!variant \mathvariantslot\fam {\p_size}%
312   \orelse\ifcstok{\lastnamedcs}\v!small
313     \s!variant {(\p_size)+\plusone}%
314   \fi}
315
316\def\math_fenced_left
317  {\advanceby\c_math_fence_nesting\plusone
318   \math_fenced_common\Uleft\c!leftclass\math_fenced_p_left\c!leftsource\c!leftcolor}
319
320\def\math_fenced_right
321  {\math_fenced_common\Uright\c!rightclass\math_fenced_p_right\c!rightsource\c!rightcolor
322   \advanceby\c_math_fence_nesting\minusone}
323
324\def\math_fenced_middle_normal
325  {%\beginmathgroup %doesn't work well with color etc
326   \math_fenced_common\Umiddle\c!middleclass\math_fenced_p_middle\c!middlesource\c!middlecolor
327   }%\endmathgroup}
328
329\def\math_fenced_middle_sized
330  {\c_math_fenced_sized\conditionaltrue
331   \math_fenced_middle_normal
332   \c_math_fenced_sized\conditionalfalse}
333
334\appendtoks
335    \let\math_fenced_middle\math_fenced_middle_normal
336    \enforced\let\fence\math_fenced_direct
337\to \everymathatom
338
339\let\math_fenced_middle\math_fenced_middle_normal
340
341\def\math_fenced_p_left
342  {\ifconditional\c_math_fenced_mirror
343     \ifconditional\c_math_right_to_left
344       \mathfenceparameter\c!right
345     \else
346       \mathfenceparameter\c!left
347     \fi
348   \else
349     \mathfenceparameter\c!left
350   \fi}
351
352\def\math_fenced_p_middle
353  {\mathfenceparameter\c!middle}%
354
355\def\math_fenced_p_right
356  {\ifconditional\c_math_fenced_mirror
357     \ifconditional\c_math_right_to_left
358       \mathfenceparameter\c!left
359     \else
360       \mathfenceparameter\c!right
361     \fi
362   \else
363     \mathfenceparameter\c!right
364   \fi}
365
366\aliased\let\fence \relax
367\aliased\let\fenced\relax
368
369\protected\def\math_fenced_middle_bar  {\mfence |\relax}
370\protected\def\math_fenced_middle_colon{\mfence :\relax}
371\protected\def\math_fenced_middle_comma{\mathatom \s!leftclass \mathpunctuationcode \s!rightclass \mathmiddlecode {,}}
372
373\startsetups math:fence:set:bar
374    \aliased\let\suchthat\math_fenced_middle_bar
375    \aliased\let\where   \math_fenced_middle_comma
376    \aliased\let\and     \math_fenced_middle_comma
377\stopsetups
378
379\startsetups math:fence:set:colon
380    \aliased\let\suchthat\math_fenced_middle_colon
381    \aliased\let\where   \math_fenced_middle_comma
382    \aliased\let\and     \math_fenced_middle_comma
383\stopsetups
384
385\startsetups math:fence:set
386    \directsetup{math:fence:set:bar}
387\stopsetups
388
389\mutable\lettonothing\suchthat
390
391% \fastsetup{math:fence:set}
392
393\protected\def\math_fenced_middle_common
394  {\math_fenced_middle} % redefined inside atom
395
396\protected\def\math_fenced_fenced_common
397  {\startusemathstyleparameter\mathfenceparameter\c!mathstyle
398   \usesetupsparameter\mathfenceparameter
399   \enforced\let\fence\math_fenced_middle_common}
400
401\protected\def\math_fenced_fenced_start#1%
402  {\begingroup
403 %{\beginmathgroup
404   \cdef\currentmathfence{#1}%
405   \math_fenced_fenced_common
406   \math_fenced_left}
407
408\protected\def\math_fenced_fenced_stop#1%
409  {\cdef\currentmathfence{#1}%
410   \math_fenced_right
411   \stopusemathstyleparameter
412   \endgroup}
413  %\endmathgroup}
414
415\installlocalcurrenthandler \??mathfences {mathfence}
416
417%D The horizontal text variant was introduced for Alan Braslau. Because this is not
418%D used that often we only support double text arguments.
419%D
420%D Musical timestamp: I am The Moon by Tedeschi Trucks Band
421
422% \definemathfence [tupdownarrows] [text] [\c!left="2191,\c!right="2193]
423
424\def\math_fenced_check#1%
425  {\ifempty{\mathfenceparameter#1}\letmathfenceparameter#1\v!none\fi}
426
427\appendtoks
428    \math_fenced_check\c!left
429    \math_fenced_check\c!right
430\to \everysetupmathfence
431
432\appendtoks
433    \math_fenced_check\c!left
434    \math_fenced_check\c!right
435\to \everydefinemathfence
436
437\protected\def\math_fenced_horizontal_common#1#2#3#4#5% \Uwhatever class symbol source color
438  {\c_math_fenced_class\math_class_by_parameter\mathfenceparameter#2\relax
439   \edef\p_fence{#3}%
440   #1% \Uleft \Umiddle \Uleft
441   \usedcolorparameterattributes{\mathfenceparameter#5}%
442   \s!leftclass  \mathunspacedcode
443   \s!rightclass \mathunspacedcode
444   \s!class      \mathunspacedcode
445   \s!source     {\namedboxanchor{\mathfenceparameter#4}}%
446   \Umathchar\mathghostcode\fam{\p_fence}}
447
448\tolerant\protected\def\math_fenced_horizontal#1#*[#S#2]#:#*#3#4%
449  {\mathord \bgroup % class here
450     \setlocalmathfencecurrent{#1}% \cdef\currentmathfence{#1}%
451     \setupcurrentmathfence[#2]%
452   % \usemathstyleparameter\mathfenceparameter\c!mathstyle
453     \setmathsmalltextbox\scratchboxone\hbox{\usemathfencestyleandcolor\c!leftstyle \c!leftcolor #3}%
454     \setmathsmalltextbox\scratchboxtwo\hbox{\usemathfencestyleandcolor\c!rightstyle\c!rightcolor#4}%
455     \let\math_fenced_common\math_fenced_horizontal_common
456     \edef\p_fenced_middle{\mathfenceparameter\c!middle}%
457     \ifempty\p_fenced_middle\else
458       \letmathfenceparameter\c!left \p_fenced_middle
459       \letmathfenceparameter\c!right\zerocount
460     \fi
461     \scratchdistance{\mathfenceparameter\c!distance}%
462     \box\scratchboxone
463     \kern\scratchdistance
464     \math_fenced_fenced_start\currentmathfence
465     \math_fenced_fenced_stop \currentmathfence
466     \kern\scratchdistance
467     \box\scratchboxtwo
468   \egroup}
469
470\tolerant\protected\def\math_fenced_fenced#1%
471  {\ifcstok{\namedmathfenceparameter{#1}\c!text}\v!yes % not the best keyword
472     \expandafter\math_fenced_horizontal
473   \else
474     \expandafter\math_fenced_vertical
475   \fi{#1}}
476
477% two step because we don't want to define text itself as command
478
479\definemathfence
480  [\v!text]
481
482\setupmathfence
483  [\v!text]
484  [\c!text=\v!yes,
485   \c!define=\v!yes,
486   \c!distance=.125\emwidth]
487
488% \tolerant\protected\def\math_fenced_vertical#1#*[#S#2]%
489%   {\begingroup
490%  %{\beginmathgroup
491%    \setlocalmathfencecurrent{#1}% \cdef\currentmathfence{#1}%
492%    \c_math_fenced_level_mode\conditionalfalse
493%    \resetmathfenceparameter\c!size
494%    \letmathfenceparameter\c!factor\v!auto
495%    \ifparameter#2\or
496%      \setupcurrentmathfence[#2]%
497%    \fi
498%    \math_fenced_fenced_common
499%    \math_fenced_fenced_indeed_adapt}
500
501% \protected\def\math_fenced_fenced_indeed_adapt#1%
502%   {\c_math_fenced_sized\conditionalfalse
503%    \math_fenced_left
504%    #1%
505%    \c_math_fenced_sized\conditionalfalse
506%    \math_fenced_right
507%    \math_fenced_fenced_indeed_finish}
508
509% \protected\def\math_fenced_fenced_indeed_finish
510%   {\stopusemathstyleparameter
511%    \endgroup}
512%   %\endmathgroup}
513
514\tolerant\protected\def\math_fenced_vertical#1#*[#S#2]#:#3%
515 %{\beginmathgroup
516  {\begingroup
517   \setlocalmathfencecurrent{#1}% \cdef\currentmathfence{#1}%
518   \c_math_fenced_level_mode\conditionalfalse
519   \resetmathfenceparameter\c!size
520   \letmathfenceparameter\c!factor\v!auto
521   \ifparameter#2\or
522     \setupcurrentmathfence[#2]%
523   \fi
524   \math_fenced_fenced_common
525   \c_math_fenced_sized\conditionalfalse
526   \math_fenced_left
527   #3%
528   \c_math_fenced_sized\conditionalfalse
529   \math_fenced_right
530   \stopusemathstyleparameter
531   \endgroup}
532  %\endmathgroup}
533
534\protected\def\math_fenced_direct[#1]%
535  {\math_fenced_fenced{#1}}
536
537\appendtoks
538    \enforced\let\fenced\math_fenced_direct
539% \to \everysetupmathematics
540\to \everyswitchmathematics
541
542\permanent\tolerant\protected\def\startmathfenced[#1]#*[#S#2]%
543  {\begingroup
544   \cdef\currentmathfence{#1}%
545   \setupcurrentmathfence[#2]%
546   \math_fenced_fenced_start{#1}}
547
548\permanent\protected\def\stopmathfenced
549  {\math_fenced_fenced_stop\currentmathfence
550   \endgroup}
551
552\protected\def\math_fenced_start_wrap#1%
553  {\begingroup
554   \edef\m_math_fenced_wrap{#1}%
555   \ifempty\m_math_fenced_wrap \else
556     \math_fenced_fenced_start\m_math_fenced_wrap
557   \fi}
558
559\protected\def\math_fenced_stop_wrap
560  {\ifempty\m_math_fenced_wrap \else
561     \math_fenced_fenced_stop\m_math_fenced_wrap
562   \fi
563   \endgroup}
564
565% for torture testing mikael sundqvist:
566%
567% \setupmathfence[brace][middle=124]
568%
569% \im{\fenced[brace]        {\vec{x}\in\reals^3\middle\vert \vec{x}\neq \vec{0}}}
570% \im{\fenced[brace]        {\vec{x}\in\reals^3\mid         \vec{x}\neq \vec{0}}}
571% \im{\fenced[brace][size=0]{\vec{x}\in\reals^3\fence       \vec{x}\neq \vec{0}}}
572
573\aliased\let\normalmid\mid
574
575\protected\def\mid{\ifcase\c_math_fence_nesting\normalmid\else\middle\vert\fi}
576
577% cases are defined in math-ali:
578
579\definemathfence [cases]   [\c!left="007B,\c!right=\v!none]
580\definemathfence [sesac]   [\c!left=\v!none,\c!right="007D]
581\definemathfence [tekcarb] [\c!left="005D,\c!right="005B]   % used for xıɹʇɐɯ
582
583%D This is new:
584%D
585%D \starttyping
586%D $ \F0 \left( x + \F1 \left( x \right) + x \right) $
587%D $
588%D   \F0 \left( x + \F1 \left( x + \F2 \left( x + \F3 \left( x + \F4 \left( x +
589%D   2
590%D   + x \right) + x \right) + x \right) + x \right) + x \right)
591%D $
592%D $ \F1 \left( x + \F1 \left( x \right) + x \right) $
593%D $ \F3 \left( x + \F1 \left( x \right) + x \right) $
594%D $ \F1 \left( x + \F4 \left( x \right) + x \right) $
595%D $ \F4 \left( x + \F- \left( x \right) + x \right) $
596%D $ \F4
597%D     \left( 1 +
598%D         \F- \left( 2 +
599%D             \F* \left( 3 +
600%D                 4
601%D             \right)
602%D             + 5 +
603%D             \F- \left( 6 +
604%D                 7
605%D             \right)
606%D         \right)
607%D         + 8
608%D     \right)
609%D $
610%D \stoptyping
611%D
612%D \starttyping
613%D \startTEXpage[offset=1dk,width=20dk]
614%D   \ruledhbox{$ \F3 \left( 1 + \F2 \left( a + b \right) + \left( a + b \right) \right) $}\par
615%D   \ruledhbox{$ \left( 1 + \F3 \left( a + b \right) + \left( a + b \right) \right) $}\par
616%D   \ruledhbox{$ \F3 \left( 1 + \F0 \left( a + b \right) \right) $}\par
617%D   \ruledhbox{$ \F3 \left( 1 + \F= \left( a + b \right) \right) $}\par
618%D   \ruledhbox{$ \F4 \left( 1 + \fenced[parenthesis]{a + b} \right) $}\par
619%D   \ruledhbox{$ \F3 \left( 1 + \F- \left( a + b \right) \right) $}\par
620%D   \ruledhbox{$ \left( \frac{1}{1+x} \right) $}\par
621%D   \ruledhbox{$ \left( \frac{1}{1+x} \right) $}\par
622%D \stopTEXpage
623%D \stoptyping
624
625\newinteger    \c_math_fenced_level
626\newconditional\c_math_fenced_level_mode
627
628\integerdef\c_math_fenced_stack \zerocount
629
630\installmacrostack \c_math_fenced_stack
631
632\installcorenamespace{fencelevels}
633\installcorenamespace{fencestack}
634
635\defcsname\??fencelevels+\endcsname{\advanceby\c_math_fenced_level\plusone  }
636\defcsname\??fencelevels-\endcsname{\advanceby\c_math_fenced_level\minusone }
637\defcsname\??fencelevels=\endcsname          {\c_math_fenced_level\zerocount}
638
639\letcsname\??fencelevels*\endcsname\donothing
640
641\def\math_fenced_check_size_mismatch
642 {\ifnum\c_math_fence_check=\c_math_fence_nesting
643    \c_math_fenced_level_mode\conditionalfalse
644    \c_math_fenced_level\zerocount
645  \fi}
646
647\permanent\protected\def\F#1%
648  {\ifconditional\c_math_fenced_level_mode\else
649     \c_math_fence_check\c_math_fence_nesting
650   \fi
651   \c_math_fenced_level_mode\conditionaltrue
652   \ifchknum#1\or
653     \c_math_fenced_level#1\relax
654   \orelse\ifcsname\??fencelevels#1\endcsname
655     \lastnamedcs
656   \else
657     \c_math_fenced_level\zerocount
658   \fi}
659
660\definemathfence [parenthesis] [\c!left="0028,\c!right="0029,define=yes]% some kind of meaning
661\definemathfence [bracket]     [\c!left="005B,\c!right="005D,define=yes]% some kind of meaning
662\definemathfence [brace]       [\c!left="007B,\c!right="007D,define=yes]% some kind of meaning
663\definemathfence [bar]         [\c!left="007C,\c!right="007C]
664\definemathfence [doublebar]   [\c!left="2016,\c!right="2016]
665\definemathfence [triplebar]   [\c!left="2980,\c!right="2980]
666\definemathfence [angle]       [\c!left="27E8,\c!right="27E9]
667\definemathfence [doubleangle] [\c!left="27EA,\c!right="27EB]
668\definemathfence [solidus]     [\c!left="2044,\c!right="2044]
669\definemathfence [ceiling]     [\c!left="2308,\c!right="2309,define=yes]% Have meaning
670\definemathfence [floor]       [\c!left="230A,\c!right="230B,define=yes]% Have meaning
671\definemathfence [moustache]   [\c!left="23B0,\c!right="23B1]
672\definemathfence [uppercorner] [\c!left="231C,\c!right="231D]
673\definemathfence [lowercorner] [\c!left="231E,\c!right="231F]
674\definemathfence [group]       [\c!left="27EE,\c!right="27EF]
675\definemathfence [openbracket] [\c!left="27E6,\c!right="27E7]
676
677\definemathfence [nothing]
678
679\definemathfence [mirrored] % \v!mirrored
680
681\definemathfence [mirroredparenthesis] [mirrored] [\c!right="0028,\c!left="0029]
682\definemathfence [mirroredbracket]     [mirrored] [\c!right="005B,\c!left="005D]
683\definemathfence [mirroredbrace]       [mirrored] [\c!right="007B,\c!left="007D]
684\definemathfence [mirroredbar]         [mirrored] [\c!right="007C,\c!left="007C]
685\definemathfence [mirroreddoublebar]   [mirrored] [\c!right="2016,\c!left="2016]
686\definemathfence [mirroredtriplebar]   [mirrored] [\c!right="2980,\c!left="2980]
687\definemathfence [mirroredangle]       [mirrored] [\c!right="27E8,\c!left="27E9]
688\definemathfence [mirroreddoubleangle] [mirrored] [\c!right="27EA,\c!left="27EB]
689\definemathfence [mirroredsolidus]     [mirrored] [\c!right="2044,\c!left="2044]
690\definemathfence [mirroredceiling]     [mirrored] [\c!right="2308,\c!left="2309]
691\definemathfence [mirroredfloor]       [mirrored] [\c!right="230A,\c!left="230B]
692\definemathfence [mirroredmoustache]   [mirrored] [\c!right="23B0,\c!left="23B1]
693\definemathfence [mirroreduppercorner] [mirrored] [\c!right="231C,\c!left="231D]
694\definemathfence [mirroredlowercorner] [mirrored] [\c!right="231E,\c!left="231F]
695\definemathfence [mirroredgroup]       [mirrored] [\c!right="27EE,\c!left="27EF]
696\definemathfence [mirroredopenbracket] [mirrored] [\c!right="27E6,\c!left="27E7]
697
698\definemathfence [mirrorednothing]     [mirrored]
699
700%D A bonus:
701
702\pushoverloadmode
703
704\immutable\protected\def\Lparenthesis         {\math_fenced_fenced_start{parenthesis}}          \immutable\protected\def\Rparenthesis         {\math_fenced_fenced_stop {parenthesis}}
705\immutable\protected\def\Lbracket             {\math_fenced_fenced_start{bracket}}              \immutable\protected\def\Rbracket             {\math_fenced_fenced_stop {bracket}}
706\immutable\protected\def\Lbrace               {\math_fenced_fenced_start{brace}}                \immutable\protected\def\Rbrace               {\math_fenced_fenced_stop {brace}}
707\immutable\protected\def\Langle               {\math_fenced_fenced_start{angle}}                \immutable\protected\def\Rangle               {\math_fenced_fenced_stop {angle}}
708\immutable\protected\def\Ldoubleangle         {\math_fenced_fenced_start{doubleangle}}          \immutable\protected\def\Rdoubleangle         {\math_fenced_fenced_stop {doubleangle}}
709\immutable\protected\def\Lbar                 {\math_fenced_fenced_start{bar}}                  \immutable\protected\def\Rbar                 {\math_fenced_fenced_stop {bar}}
710\immutable\protected\def\Ldoublebar           {\math_fenced_fenced_start{doublebar}}            \immutable\protected\def\Rdoublebar           {\math_fenced_fenced_stop {doublebar}}
711\immutable\protected\def\Ltriplebar           {\math_fenced_fenced_start{triplebar}}            \immutable\protected\def\Rtriplebar           {\math_fenced_fenced_stop {triplebar}}
712\immutable\protected\def\Lsolidus             {\math_fenced_fenced_start{solidus}}              \immutable\protected\def\Rsolidus             {\math_fenced_fenced_stop {solidus}}
713\immutable\protected\def\Lfloor               {\math_fenced_fenced_start{floor}}                \immutable\protected\def\Rfloor               {\math_fenced_fenced_stop {floor}}
714\immutable\protected\def\Lceiling             {\math_fenced_fenced_start{ceiling}}              \immutable\protected\def\Rceiling             {\math_fenced_fenced_stop {ceiling}}
715\immutable\protected\def\Lmoustache           {\math_fenced_fenced_start{moustache}}            \immutable\protected\def\Rmoustache           {\math_fenced_fenced_stop {moustache}}
716\immutable\protected\def\Luppercorner         {\math_fenced_fenced_start{uppercorner}}          \immutable\protected\def\Ruppercorner         {\math_fenced_fenced_stop {uppercorner}}
717\immutable\protected\def\Llowercorner         {\math_fenced_fenced_start{lowercorner}}          \immutable\protected\def\Rlowercorner         {\math_fenced_fenced_stop {lowercorner}}
718\immutable\protected\def\Lgroup               {\math_fenced_fenced_start{group}}                \immutable\protected\def\Rgroup               {\math_fenced_fenced_stop {group}}
719\immutable\protected\def\Lopenbracket         {\math_fenced_fenced_start{openbracket}}          \immutable\protected\def\Ropenbracket         {\math_fenced_fenced_stop {openbracket}}
720\immutable\protected\def\Lnothing             {\math_fenced_fenced_start{nothing}}              \immutable\protected\def\Rnothing             {\math_fenced_fenced_stop {nothing}}
721
722\immutable\protected\def\Lparenthesismirrored {\math_fenced_fenced_stop {mirroredparenthesis}}  \immutable\protected\def\Rparenthesismirrored {\math_fenced_fenced_start{mirroredparenthesis}}
723\immutable\protected\def\Lbracketmirrored     {\math_fenced_fenced_stop {mirroredbracket}}      \immutable\protected\def\Rbracketmirrored     {\math_fenced_fenced_start{mirroredbracket}}
724\immutable\protected\def\Lbracemirrored       {\math_fenced_fenced_stop {mirroredbrace}}        \immutable\protected\def\Rbracemirrored       {\math_fenced_fenced_start{mirroredbrace}}
725\immutable\protected\def\Langlemirrored       {\math_fenced_fenced_stop {mirroredangle}}        \immutable\protected\def\Ranglemirrored       {\math_fenced_fenced_start{mirroredangle}}
726\immutable\protected\def\Ldoubleanglemirrored {\math_fenced_fenced_stop {mirroreddoubleangle}}  \immutable\protected\def\Rdoubleanglemirrored {\math_fenced_fenced_start{mirroreddoubleangle}}
727\immutable\protected\def\Lbarmirrored         {\math_fenced_fenced_stop {mirroredbar}}          \immutable\protected\def\Rbarmirrored         {\math_fenced_fenced_start{mirroredbar}}
728\immutable\protected\def\Ldoublebarmirrored   {\math_fenced_fenced_stop {mirroreddoublebar}}    \immutable\protected\def\Rdoublebarmirrored   {\math_fenced_fenced_start{mirroreddoublebar}}
729\immutable\protected\def\Ltriplebarmirrored   {\math_fenced_fenced_stop {mirroredtriplebar}}    \immutable\protected\def\Rtriplebarmirrored   {\math_fenced_fenced_start{mirroredtriplebar}}
730\immutable\protected\def\Lsolidusmirrored     {\math_fenced_fenced_stop {mirroredsolidus}}      \immutable\protected\def\Rsolidusmirrored     {\math_fenced_fenced_start{mirroredsolidus}}
731\immutable\protected\def\Lfloormirrored       {\math_fenced_fenced_stop {mirroredfloor}}        \immutable\protected\def\Rfloormirrored       {\math_fenced_fenced_start{mirroredfloor}}
732\immutable\protected\def\Lceilingmirrored     {\math_fenced_fenced_stop {mirroredceiling}}      \immutable\protected\def\Rceilingmirrored     {\math_fenced_fenced_start{mirroredceiling}}
733\immutable\protected\def\Lmoustachemirrored   {\math_fenced_fenced_stop {mirroredmoustache}}    \immutable\protected\def\Rmoustachemirrored   {\math_fenced_fenced_start{mirroredmoustache}}
734\immutable\protected\def\Luppercornermirrored {\math_fenced_fenced_stop {mirroreduppercorner}}  \immutable\protected\def\Ruppercornermirrored {\math_fenced_fenced_start{mirroreduppercorner}}
735\immutable\protected\def\Llowercornermirrored {\math_fenced_fenced_stop {mirroredlowercorner}}  \immutable\protected\def\Rlowercornermirrored {\math_fenced_fenced_start{mirroredlowercorner}}
736\immutable\protected\def\Lgroupmirrored       {\math_fenced_fenced_stop {mirroredgroup}}        \immutable\protected\def\Rgroupmirrored       {\math_fenced_fenced_start{mirroredgroup}}
737\immutable\protected\def\Lopenbracketmirrored {\math_fenced_fenced_stop {mirroredopenbracket}}  \immutable\protected\def\Ropenbracketmirrored {\math_fenced_fenced_start{mirroredopenbracket}}
738\immutable\protected\def\Lnothingmirrored     {\math_fenced_fenced_stop {mirrorednothing}}      \immutable\protected\def\Rnothingmirrored     {\math_fenced_fenced_start{mirrorednothing}}
739
740% These tortoise chars almost only exist in stix (and ar not commonly used)
741
742% \definemathfence [interval]                     [\c!left="2997,\c!right="2998]
743% \definemathfence [openinterval]      [interval] [\c!left="2998,\c!right="2998]
744% \definemathfence [leftopeninterval]  [interval] [\c!left="2997,\c!right="2997]
745% \definemathfence [rightopeninterval] [interval] [\c!left="2998,\c!right="2998]
746
747% Different intervals. The variants are the ones suggested by Bourbaki.
748
749\definemathfence [interval]                        [\c!left="005B,\c!right="005D,define=yes]
750\definemathfence [openinterval]         [interval] [\c!left="0028,\c!right="0029,define=yes]
751\definemathfence [closedinterval]       [interval] [\c!left="005B,\c!right="005D,define=yes]
752\definemathfence [leftopeninterval]     [interval] [\c!left="0028,\c!right="005D,define=yes]
753\definemathfence [rightopeninterval]    [interval] [\c!left="005B,\c!right="0029,define=yes]
754\definemathfence [varopeninterval]      [interval] [\c!left="005D,\c!right="005B,define=yes]
755\definemathfence [varleftopeninterval]  [interval] [\c!left="005D,\c!right="005D,define=yes]
756\definemathfence [varrightopeninterval] [interval] [\c!left="005B,\c!right="005B,define=yes]
757\definemathfence [integerinterval]      [interval] [\c!left="27E6,\c!right="27E7,define=yes]
758
759\immutable\protected\def\Linterval   {\math_fenced_fenced_start{interval}}
760\immutable\protected\def\Lointerval  {\math_fenced_fenced_start{openinterval}}
761\immutable\protected\def\Llointerval {\math_fenced_fenced_start{leftopeninterval}}
762\immutable\protected\def\Lrointerval {\math_fenced_fenced_start{rightopeninterval}}
763
764\immutable\protected\def\Rinterval   {\math_fenced_fenced_stop {interval}}
765\immutable\protected\def\Rointerval  {\math_fenced_fenced_stop {openinterval}}
766\immutable\protected\def\Rlointerval {\math_fenced_fenced_stop {leftopeninterval}}
767\immutable\protected\def\Rrointerval {\math_fenced_fenced_stop {rightopeninterval}}
768
769% \startformula
770% \left{ \frac{1}{a} \right}
771% \left[ \frac{1}{b} \right]
772% \left( \frac{1}{c} \right)
773% \left< \frac{1}{d} \right>
774% \left| \frac{1}{e} \right|
775% \stopformula
776
777\popoverloadmode
778
779\installcorenamespace{mathleft}
780\installcorenamespace{mathright}
781\installcorenamespace{mathmiddle}
782
783\pushoverloadmode
784
785% \protected\def\left  {\afterassignment\math_left  \let\nexttoken}
786% \protected\def\right {\afterassignment\math_right \let\nexttoken}
787% \protected\def\middle{\afterassignment\math_middle\let\nexttoken}
788
789% \im { \left{       \frac{1}{2} \right}       }
790% \im { \left\bgroup \frac{1}{2} \right\egroup }
791% \im { \left\{      \frac{1}{2} \right\}      }
792% \im { \left\lbrace \frac{1}{2} \right\rbrace }
793
794\lettonothing\math_fenced_x_p_left
795\lettonothing\math_fenced_x_p_right
796\lettonothing\math_fenced_x_p_middle
797
798\def\math_fenced_x_left
799  {\advanceby\c_math_fence_nesting\plusone
800   \ifx\math_fenced_x_p_left\bgroup\let\math_fenced_x_p_left\letterleftbrace\fi
801   \math_fenced_common\Uleft\c!leftclass\math_fenced_x_p_left\c!leftsource\c!leftcolor}
802
803\def\math_fenced_x_right
804  {\ifx\math_fenced_x_p_right\egroup\let\math_fenced_x_p_right\letterrightbrace\fi
805   \math_fenced_common\Uright\c!rightclass\math_fenced_x_p_right\c!rightsource\c!rightcolor
806   \advanceby\c_math_fence_nesting\minusone}
807
808\def\math_fenced_x_middle
809  {%\beginmathgroup %doesn't work well with color etc
810   \math_fenced_common\Umiddle\c!middleclass\math_fenced_x_p_middle\c!middlesource\c!middlecolor
811   }%\endmathgroup}
812
813% the expandafter permits \left\tocharacter...
814
815\protected\def\lfence{\afterassignment\math_fenced_x_left  \expandafter\let\expandafter\math_fenced_x_p_left}
816\protected\def\rfence{\afterassignment\math_fenced_x_right \expandafter\let\expandafter\math_fenced_x_p_right}
817\protected\def\mfence{\afterassignment\math_fenced_x_middle\expandafter\let\expandafter\math_fenced_x_p_middle}
818
819\aliased\let\left  \lfence
820\aliased\let\right \rfence
821\aliased\let\middle\mfence
822
823\popoverloadmode
824
825% \let\leftorright\relax
826
827\newconditional\c_math_fenced_unknown  \c_math_fenced_unknown\conditionaltrue
828
829% \permanent\protected\def\installmathfencepair#1#2#3#4%
830%   {\letcsname\??mathleft \normalmeaningless#1\endcsname#2%
831%    \letcsname\??mathright\normalmeaningless#3\endcsname#4}
832
833\permanent\protected\def\installmathfencepair#1#2#3#4%
834  {}
835
836% \def\math_unknown_left  {\ifconditional\c_math_fenced_unknown\Uleft              \nexttoken\fi}
837% \def\math_unknown_right {\ifconditional\c_math_fenced_unknown\Uright             \nexttoken\fi}
838% \def\math_unknown_middle{\ifconditional\c_math_fenced_unknown\Umiddle nooverflow \nexttoken\fi}
839
840% \def\math_unknown_left
841%   {\let\math_fenced_p_left\nexttoken
842%    \math_fenced_left}
843%
844% \def\math_unknown_right
845%   {\let\math_fenced_p_right\nexttoken
846%    \math_fenced_right}
847%
848% \def\math_unknown_middle
849%   {\let\math_fenced_p_middle\nexttoken
850%    \math_fenced_middle}
851%
852% \letcsname\??mathleft  \s!unknown\endcsname\math_unknown_left
853% \letcsname\??mathright \s!unknown\endcsname\math_unknown_right
854% \letcsname\??mathmiddle\s!unknown\endcsname\math_unknown_middle
855%
856% \def\math_left
857%   {\ifcsname\??mathleft\normalmeaningless\nexttoken\endcsname
858%      \expandafter\lastnamedcs
859%    \else
860%      \expandafter\math_unknown_left
861%    \fi}
862%
863% \def\math_right
864%   {\ifcsname\??mathright\normalmeaningless\nexttoken\endcsname
865%      \expandafter\lastnamedcs
866%    \else
867%      \expandafter\math_unknown_right
868%    \fi}
869%
870% \def\math_middle
871%   {\ifcsname\??mathmiddle\normalmeaningless\nexttoken\endcsname
872%      \expandafter\lastnamedcs
873%    \else
874%      \expandafter\math_unknown_middle
875%    \fi}
876%
877% \permanent\protected\def\lfence#1%
878%   {\let\nexttoken#1%
879%    \ifcsname\??mathleft\normalmeaningless\nexttoken\endcsname
880%      \expandafter\lastnamedcs
881%    \else
882%      \expandafter\math_unknown_left
883%    \fi}
884%
885% \permanent\protected\def\rfence#1%
886%   {\let\nexttoken#1%
887%    \ifcsname\??mathright\normalmeaningless\nexttoken\endcsname
888%      \expandafter\lastnamedcs
889%    \else
890%      \expandafter\math_unknown_right
891%    \fi}
892%
893% \permanent\protected\def\mfence#1%
894%   {\let\nexttoken#1%
895%    \ifcsname\??mathmiddle\normalmeaningless\nexttoken\endcsname
896%      \expandafter\lastnamedcs
897%    \else
898%      \expandafter\math_unknown_middle
899%    \fi}
900
901% \normalexpanded{\installmathfencepair {|\detokenize {|}} \Ldoublebar {|\detokenize {|}} \Rdoublebar}
902% \normalexpanded{\installmathfencepair {|\detokenize{||}} \Ltriplebar {|\detokenize{||}} \Rtriplebar}
903%
904% \installmathfencepair \bgroup \Lbrace         \egroup \Rbrace
905% \installmathfencepair \egroup \Rbracemirrored \bgroup \Lbracemirrored
906%
907% \installmathfencepair \letteropenbrace \Lbrace \letterclosebrace \Rbrace % as we escape in mp textexts
908%
909% \installmathfencepair . \Lnothing             . \Rnothing
910% \installmathfencepair . \Rnothingmirrored     . \Lnothingmirrored
911%
912% \installmathfencepair [ \Lbracket             ] \Rbracket
913% \installmathfencepair ] \Rbracketmirrored     [ \Lbracketmirrored
914%
915% \installmathfencepair ( \Lparenthesis         ) \Rparenthesis
916% \installmathfencepair ) \Rparenthesismirrored ( \Lparenthesismirrored
917%
918% \installmathfencepair < \Langle               > \Rangle
919% \installmathfencepair > \Ranglemirrored       < \Langlemirrored
920%
921% \installmathfencepair / \Lsolidus             / \Rsolidus
922% %installmathfencepair / \Rsolidusmirrored     / \Lsolidusmirrored
923%
924% \installmathfencepair | \Lbar                 | \Rbar
925% %installmathfencepair | \Rbarmirrored         | \Lbarmirrored
926%
927% \installmathfencepair ⌊ \Lfloor               ⌋ \Rfloor
928% \installmathfencepair ⌋ \Rfloormirrored       ⌊ \Lfloormirrored
929% \installmathfencepair ⌈ \Lceiling             ⌉ \Rceiling
930% \installmathfencepair ⌉ \Rceilingmirrored     ⌈ \Lceilingmirrored
931%
932% \installmathfencepair ⟨ \Langle               ⟩ \Rangle
933% \installmathfencepair ⟩ \Ranglemirrored       ⟨ \Langlemirrored
934%
935% \installmathfencepair ⟪ \Ldoubleangle         ⟫ \Rdoubleangle
936% \installmathfencepair ⟫ \Rdoubleanglemirrored ⟪ \Ldoubleanglemirrored
937%
938% \installmathfencepair ‖ \Ldoublebar           ‖ \Rdoublebar
939% %installmathfencepair ‖ \Rdoublebarmirrored   ‖ \Ldoublebarmirrored
940%
941% \installmathfencepair ⦀ \Ltriplebar           ⦀ \Rtriplebar
942% %installmathfencepair ⦀ \Rtriplebarmirrored   ⦀ \Ltriplebarmirrored
943%
944% % \installmathfencepair { \Lbrace             } \Rbrace
945% % \installmathfencepair } \Rbracemirrored     { \Lbracemirrored
946%
947% \installmathfencepair ⦗ \Linterval            ⦘ \Rinterval
948
949% \appendtoks
950%     \ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox
951% \to \everysetupmathematics
952% \to \everyswitchmathematics
953
954% We unofficial support some synonyms as we need them for some fuzzy web related math.
955
956% The names in char-def.lua (historic mess):
957
958\pushoverloadmode
959
960\aliased\let\lbrack      \lbracket
961\aliased\let\rbrack      \rbracket
962\aliased\let\lceiling    \lceil
963\aliased\let\rceiling    \rceil
964\aliased\let\lparenthesis\lparent
965\aliased\let\rparenthesis\rparent
966\aliased\let\lparen      \lparent
967\aliased\let\rparen      \rparent
968
969% Just defined:
970
971\aliased\let\Lceil  \Lceiling
972\aliased\let\Rceil  \Rceiling
973\aliased\let\Lparent\Lparenthesis
974\aliased\let\Rparent\Rparenthesis
975\aliased\let\Lparen \Lparenthesis
976\aliased\let\Rparen \Rparenthesis
977
978% \installmathfencepair \lbrace       \Lbrace       \rbrace       \Rbrace
979% \installmathfencepair \lbracket     \Lbracket     \rbracket     \Rbracket
980% \installmathfencepair \lbrack       \Lbracket     \rbracket     \Rbracket
981% \installmathfencepair \lparenthesis \Lparenthesis \rparenthesis \Rparenthesis
982% \installmathfencepair \lparent      \Lparenthesis \rparent      \Rparenthesis
983% \installmathfencepair \lparen       \Lparenthesis \rparen       \Rparenthesis
984% \installmathfencepair \langle       \Langle       \rangle       \Rangle
985% \installmathfencepair \llangle      \Ldoubleangle \rrangle      \Rdoubleangle
986% %installmathfencepair \lbar         \Lbar         \rbar         \Rbar
987% \installmathfencepair \lVert        \Ldoublebar   \rVert        \Rdoublebar
988% \installmathfencepair \vert         \Lbar         \vert         \Rbar
989% \installmathfencepair \solidus      \Lsolidus     \solidus      \Rsolidus
990% \installmathfencepair \lfloor       \Lfloor       \rfloor       \Rfloor
991% \installmathfencepair \lceiling     \Lceiling     \rceiling     \Rceiling
992% \installmathfencepair \lceil        \Lceiling     \rceil        \Rceiling
993
994% \installmathfencepair \ulcorner     \Luppercorner \urcorner     \Ruppercorner
995% \installmathfencepair \llcorner     \Llowercorner \lrcorner     \Rlowercorner
996% \installmathfencepair \lmoustache   \Lmoustache   \rmoustache   \Rmoustache
997% \installmathfencepair \llbracket    \Lopenbracket \rrbracket    \Ropenbracket
998% \installmathfencepair \lgroup       \Lgroup       \rgroup       \Rgroup
999
1000% \installmathfencepair \linterval    \Linterval    \rinterval    \Rinterval
1001% %installmathfencepair \linterv      \Linterval    \rinterv      \Rinterval
1002% \installmathfencepair \lointerval   \Linterval    \rointerval   \Rinterval
1003% \installmathfencepair \llointerval  \Llointerval  \rlointerval  \Rlointerval
1004% \installmathfencepair \lrointerval  \Lrointerval  \rrointerval  \Rrointerval
1005
1006\aliased\let\textlbar\lbar \aliased\let\mathlbar\Lbar
1007\aliased\let\textrbar\lbar \aliased\let\mathrbar\Rbar
1008
1009\immutable\protected\def\lbar{\mathortext\mathlbar\textlbar}
1010\immutable\protected\def\rbar{\mathortext\mathrbar\textrbar}
1011
1012% \setupmathfences[color=darkgreen]
1013
1014% \permanent\protected\def\{{\mathortext\lbrace      \letterleftbrace       } % or maybe a chardef
1015% \permanent\protected\def\}{\mathortext\rbrace      \letterrightbrace      } % or maybe a chardef
1016% \permanent\protected\def\[{\mathortext\lbracket    \letterleftbracket     } % or maybe a chardef
1017% \permanent\protected\def\]{\mathortext\rbracket    \letterrightbracket    } % or maybe a chardef
1018% \permanent\protected\def\({\mathortext\lparenthesis\letterleftparenthesis } % or maybe a chardef
1019% \permanent\protected\def\){\mathortext\rparenthesis\letterrightparenthesis} % or maybe a chardef
1020% \permanent\protected\def\|{\mathortext\vert        \letterbar             } % or maybe a chardef
1021% %permanent\protected\def\/{\mathortext\solidus     \letterslash           } % or maybe a chardef
1022%
1023% \installmathfencepair \{ \Lbrace        \} \Rbrace
1024% \installmathfencepair \[ \Lbracket      \] \Rbracket
1025% \installmathfencepair \( \Lparenthesis  \) \Rparenthesis
1026% \installmathfencepair \< \Langle        \> \Rangle
1027% \installmathfencepair \| \Lbar          \| \Rbar
1028
1029% isn't that already the case .. still needed in lua mode ?
1030
1031\aliased\let\{\letterleftbrace
1032\aliased\let\}\letterrightbrace
1033\aliased\let\[\letterleftbracket
1034\aliased\let\]\letterrightbracket
1035\aliased\let\(\letterleftparenthesis
1036\aliased\let\)\letterrightparenthesis
1037\aliased\let\|\letterbar
1038%aliased\let\/\letterslash % italic correction
1039
1040\popoverloadmode
1041
1042%D As we have overloaded \type {\left} and \type {\right} we also need a more
1043%D clever version of the following:
1044
1045% alternatives:
1046%
1047% small: step 1
1048% big  : take step from lfg
1049
1050\permanent\protected\def\choosemathbig
1051  {\mathortext\math_choosemathbig_math\math_choosemathbig_text}
1052
1053\protected\def\math_choosemathbig_math#1#2% so we accept \big{||} as well
1054  {\begingroup
1055   \edef\p_size{#1}%
1056   \Uvextensible
1057     \s!axis
1058     \s!exact
1059     \math_fenced_set_variant
1060     #2%
1061   \relax
1062   \endgroup}
1063
1064\protected\def\math_choosemathbig_text#1#2% so we accept \big{||} as well
1065  {\naturalhbox\bgroup
1066      \startimath
1067        \math_choosemathbig_math{#1}{#2}%
1068        \nulldelimiterspace\zeropoint
1069        \mathsurround\zeropoint
1070      \stopimath
1071    \egroup}
1072
1073\permanent\protected\def\mathdelimiterstep#1#2% not used, only in example
1074  {\Uvextensible
1075     \s!axis
1076     \s!exact
1077     \s!variant {#1}% always from original sizes not lfg
1078     #2%
1079   \relax}
1080
1081\definemathcommand [big]  {\choosemathbig1}
1082\definemathcommand [Big]  {\choosemathbig2}
1083\definemathcommand [bigg] {\choosemathbig3}
1084\definemathcommand [Bigg] {\choosemathbig4}
1085
1086\definemathcommand [bigl]  [\s!open]     [one] {\big}
1087\definemathcommand [bigm]  [\s!relation] [one] {\big}    % why not just middle
1088\definemathcommand [bigr]  [\s!close]    [one] {\big}
1089\definemathcommand [Bigl]  [\s!open]     [one] {\Big}
1090\definemathcommand [Bigm]  [\s!relation] [one] {\Big}
1091\definemathcommand [Bigr]  [\s!close]    [one] {\Big}
1092\definemathcommand [biggl] [\s!open]     [one] {\bigg}
1093\definemathcommand [biggm] [\s!relation] [one] {\bigg}
1094\definemathcommand [biggr] [\s!close]    [one] {\bigg}
1095\definemathcommand [Biggl] [\s!open]     [one] {\Bigg}
1096\definemathcommand [Biggm] [\s!relation] [one] {\Bigg}
1097\definemathcommand [Biggr] [\s!close]    [one] {\Bigg}
1098
1099% \definemathfence [integral] [\c!left="222B]
1100%
1101% \protected\def\Lintegral  {\math_fenced_fenced_start{integral}}
1102% \protected\def\Rintegral  {\math_fenced_fenced_stop {integral}}
1103%
1104% \installmathfencepair \lintegral \Lintegral \rintegral \Rintegral
1105%
1106% \left\lintegral
1107%     \vrule height 3cm depth 3cm
1108% \right\rintegral
1109
1110%definemathfence [fancybracket] [bracket] [define=yes,color=red]
1111
1112%D The nested fences recovery code is needed for mathml and the original
1113%D code can still be found in the mkiv file.
1114
1115\definesystemattribute[mathautofence][public]
1116
1117\let\math_fences_normal_left  \left
1118\let\math_fences_normal_right \right
1119\let\math_fences_normal_middle\middle
1120\let\math_fences_normal_both  \relax  % undefined
1121
1122\protected\def\math_fences_auto_left  #1{\c_attr_mathautofence\plusone  #1\c_attr_mathautofence\attributeunsetvalue}
1123\protected\def\math_fences_auto_right #1{\c_attr_mathautofence\plustwo  #1\c_attr_mathautofence\attributeunsetvalue}
1124\protected\def\math_fences_auto_middle#1{\c_attr_mathautofence\plusthree#1\c_attr_mathautofence\attributeunsetvalue}
1125\protected\def\math_fences_auto_both  #1{\c_attr_mathautofence\plusfour #1\c_attr_mathautofence\attributeunsetvalue}
1126
1127\permanent\let\autofenceopen  \math_fences_auto_left    % for testing
1128\permanent\let\autofenceclose \math_fences_auto_right   % for testing
1129\permanent\let\autofenceleft  \math_fences_auto_left    % for testing
1130\permanent\let\autofenceright \math_fences_auto_right   % for testing
1131\permanent\let\autofencemiddle\math_fences_auto_middle  % for testing
1132\permanent\let\autofenceboth  \math_fences_auto_both    % for testing
1133
1134% fences are used not that often (i.e. no performance issue) so we can use a state
1135% instead of \let ... also some state variable can come in handy in the future
1136
1137\newconditional\c_math_fences_auto
1138
1139\permanent\protected\def\enableautofences
1140  {\clf_enableautofences
1141   \c_math_fences_auto\conditionalfalse
1142   \glet\clf_enableautofences\relax % onlyonce anyway
1143   \enforced\permanent\protected\gdef\enableautofences{\c_math_fences_auto\conditionaltrue}%
1144   \enableautofences}
1145
1146\permanent\protected\def\disableautofences
1147  {\c_math_fences_auto\conditionalfalse}
1148
1149\permanent\protected\def\math_fences_used_left
1150  {\ifconditional\c_math_fences_auto
1151     \expandafter\math_fences_auto_left
1152   \else
1153     \expandafter\math_fences_normal_left
1154   \fi}
1155
1156\permanent\protected\def\math_fences_used_right
1157  {\ifconditional\c_math_fences_auto
1158     \expandafter\math_fences_auto_right
1159   \else
1160     \expandafter\math_fences_normal_right
1161   \fi}
1162
1163\permanent\protected\def\math_fences_used_middle
1164  {\ifconditional\c_math_fences_auto
1165     \expandafter\math_fences_auto_middle
1166   \else
1167     \expandafter\math_fences_normal_middle
1168   \fi}
1169
1170\permanent\protected\def\math_fences_used_both
1171  {\ifconditional\c_math_fences_auto
1172     \expandafter\math_fences_auto_both
1173   \else
1174     \expandafter\math_fences_normal_both
1175   \fi}
1176
1177\aliased\let\left       \math_fences_used_left
1178\aliased\let\right      \math_fences_used_right
1179\aliased\let\middle     \math_fences_used_middle
1180\aliased\let\leftorright\math_fences_used_both
1181
1182% wrappers
1183
1184\permanent\protected\def\startcheckedfences
1185  {\begingroup
1186   \enableautofences}
1187
1188\permanent\protected\def\stopcheckedfences
1189  {\endgroup}
1190
1191\appendtoks
1192    \ifempty\currentmathfence
1193        \ifcstok{\mathfenceparameter\c!state}\v!auto\enableautofences\else\disableautofences\fi
1194    \fi
1195\to \everysetupmathfence
1196
1197\permanent\protected\def\enableautofencemode {\mathcheckfencesmode\plusone}
1198\permanent\protected\def\disableautofencemode{\mathcheckfencesmode\zerocount}
1199
1200\appendtoks
1201    \ifempty\currentmathfence
1202        \ifcstok{\mathfenceparameter\c!method}\v!auto\enableautofencemode\else\disableautofencemode\fi
1203    \fi
1204\to \everysetupmathfence
1205
1206% some day default: \setupmathfences[\c!state=\v!auto]
1207
1208%D The next characters were used for constructing nicer extensibles but
1209%D nowadays we have real characters.
1210
1211\immutable\Umathchardef\braceld\zerocount \zerocount "FF07A
1212\immutable\Umathchardef\bracerd\zerocount \zerocount "FF07B
1213\immutable\Umathchardef\bracelu\zerocount \zerocount "FF07C
1214\immutable\Umathchardef\braceru\zerocount \zerocount "FF07D
1215
1216%D Some tracing:
1217
1218\definefont[mathindexfont][Mono sa .2]
1219
1220\def\math_fenced_trace_indeed
1221  {%
1222   \beginlocalcontrol
1223     \registerboxanchor
1224     \registeranchorbox
1225       \registeredboxanchor
1226       \plusone
1227       \hbox
1228          \s!anchors \boxanchorpresetcode{depth} \boxanchorpresetcode{height}
1229          \s!yoffset -.1\exheight
1230          \s!target  \registeredboxanchor
1231          \s!to      \zeropoint
1232          {\darkblue\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting}\hss}%
1233   \endlocalcontrol
1234   \s!source \registeredboxanchor
1235   }
1236
1237% \def\math_fenced_trace_indeed
1238%   {%
1239%    \beginlocalcontrol
1240%      \registerboxanchor
1241%      \registeranchorbox
1242%        \registeredboxanchor
1243%        \plusone
1244%        \ruledhbox
1245%           \s!anchors \boxanchorpresetcode{depth} \boxanchorpresetcode{height}
1246%           \s!yoffset -.1\exheight
1247%           \s!target \registeredboxanchor
1248%           \s!to \zeropoint
1249%           {\darkblue\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting B}\hss}%
1250%      \registeranchorbox
1251%        \registeredboxanchor
1252%        \plusone
1253%        \ruledhbox
1254%           \s!anchors \boxanchorpresetcode{height} \boxanchorpresetcode{depth}
1255%           \s!yoffset .1\exheight
1256%           \s!target \registeredboxanchor
1257%           \s!to \zeropoint
1258%           {\darkgreen\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting T}\hss}%
1259%      \registeranchorbox
1260%        \registeredboxanchor
1261%        \plusone
1262%        \ruledhbox
1263%           \s!anchors \boxanchorpresetcode{left} \boxanchorpresetcode{right}
1264%           \s!xoffset -.1\emwidth
1265%           \s!target \registeredboxanchor
1266%           \s!to \zeropoint
1267%           {\darkred\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting L}}%
1268%      \registeranchorbox
1269%        \registeredboxanchor
1270%        \plusone
1271%        \ruledhbox
1272%           \s!anchors \boxanchorpresetcode{right} \boxanchorpresetcode{left}
1273%           \s!xoffset .1\emwidth
1274%           \s!target \registeredboxanchor
1275%           \s!to \zeropoint
1276%           {\darkyellow\mathindexfont\ruledhbox{\the\c_math_fence_nesting R}\hss}%
1277%    \endlocalcontrol
1278%    \s!source \registeredboxanchor
1279%    }
1280
1281\installtextracker
1282   {math.fencenesting}
1283   {\let\math_fenced_trace\math_fenced_trace_indeed}
1284   {\let\math_fenced_trace\donothing}
1285
1286\mutable\integerdef\c_math_fence_level\minusone
1287
1288\appendtoks
1289    \integerdef\c_math_fence_level\minusone
1290    \c_math_fence_nesting\zerocount
1291% \to \everysetupmathematics
1292\to \everyswitchmathematics
1293
1294%D Experiment (needs an interface i.e. key/value), bars are not middle so are not
1295%D affected but \type {\mvert} is.
1296
1297\permanent\protected\def\autofences
1298  {\setmathoptions\mathopencode\numexpression
1299     \setmathoptions\mathopencode bor \autoinjectclassoptioncode
1300   \relax
1301   \setmathoptions\mathclosecode\numexpression
1302     \setmathoptions\mathclosecode bor \autoinjectclassoptioncode
1303   \relax
1304   \setmathoptions\mathmiddlecode\numexpression
1305     \setmathoptions\mathmiddlecode bor \autoinjectclassoptioncode
1306   \relax}
1307
1308%D New (to be completed):
1309
1310% $x + \tupdownarrows{left}{right} + x$
1311% $x + \tdownuparrows{left}{right} + x$
1312% $x + \tupanddownarrows[color=red,leftcolor=green,rightcolor=blue]{left}{right} + x$
1313
1314\definemathfence [tupanddownarrows][\v!text][\c!left="2191,\c!right="2193]
1315\definemathfence [tupdownarrows]   [\v!text][\c!left="21C5,\c!right=0]
1316\definemathfence [tdownuparrows]   [\v!text][\c!middle="21F5]
1317\definemathfence [tuparrow]        [\v!text][\c!middle="2191]
1318\definemathfence [tdownarrow]      [\v!text][\c!middle="2193]
1319
1320% A few meaningful definitions
1321\definemathfence [abs]         [bar]        [define=yes]
1322\definemathfence [innerproduct][angle]      [define=yes,middle=`|]
1323\definemathfence [integerpart] [bracket]    [define=yes]
1324\definemathfence [norm]        [doublebar]  [define=yes]
1325\definemathfence [set]         [brace]      [define=yes,middle=`|]
1326\definemathfence [sequence]    [parenthesis][define=yes]
1327\definemathfence [tuple]       [parenthesis][define=yes]
1328
1329\protect
1330