%D \module
%D   [       file=math-fen,
%D        version=2012.02.18,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Fences,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Math Macros / Fences}

\unprotect

% \definemathfence [fancybracket] [bracket] [define=yes,color=blue]
%
% test $|x|$ test \par
% test $||x||$ test (okay) \par
% test $a\left|\frac{1}{b}\right|c$ test \par
% test $a\left||\frac{1}{b}\right||c$ test (not okay) \par
%
% \setupmathfences [color=red]
%
% test $a\fenced[bar]{\frac{1}{b}}c$ test \par
% test $a\fenced[doublebar]{\frac{1}{b}}c$ test \par
% test $a\fenced[bracket]{\frac{1}{b}}c$ test \par
% test $a\fancybracket{\frac{1}{b}}c$ test \par

\installcorenamespace{mathfences}

\installcommandhandler \??mathfences {mathfence} \??mathfences

\aliased\let\setupmathfences\setupmathfence

\setupmathfences
  [\c!method=, % maybe always \v!auto
   \c!left=,
   \c!right=,
   \c!middle=,
   \c!mathstyle=,
   \c!color=,
   \c!symbolcolor=\mathfenceparameter\c!color,
   \c!textcolor=\mathfenceparameter\c!color,
   \c!leftcolor=\mathfenceparameter\c!symbolcolor,
   \c!middlecolor=\mathfenceparameter\c!symbolcolor,
   \c!rightcolor=\mathfenceparameter\c!symbolcolor,
   \c!define=, % was \c!command
   \c!mathclass=,
   \c!leftclass=\mathopencode,
   \c!rightclass=\mathclosecode,
   \c!middleclass=\mathmiddlecode,
   \c!leftsource=\zerocount,
   \c!middlesource=\zerocount,
   \c!rightsource=\mathfenceparameter\c!source,
   \c!source=\zerocount,
   \c!height=\zeropoint,
   \c!depth=\zeropoint,
   \c!distance=\zerocount,
   \c!topspace=\zeropoint,
   \c!bottomspace=\zeropoint,
 % \c!overflow=\v!no,
   \c!overflow=\v!auto,
   \c!alternative=\v!big,
   \c!factor=\v!auto,
   \c!snap=\mathematicsparameter\c!snap] % "28

\appendtoks
    \ifcstok{\mathfenceparameter\c!define}\v!yes
        \protected\edefcsname\currentmathfence\endcsname{\math_fenced_fenced{\currentmathfence}}%
    \fi
\to \everydefinemathfence

%D So we can do:
%D
%D \starttyping
%D $ a + \fenced[bar][size=1]   {\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=2]   {\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=3]   {\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=4]   {\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=big] {\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=Big] {\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=bigg]{\frac {b} {c}} + d $
%D $ a + \fenced[bar][size=Bigg]{\frac {b} {c}} + d $
%D $ a + \fenced[bar][factor=1] {\frac {b} {c}} + d $
%D $ a + \fenced[bar][factor=2] {\frac {b} {c}} + d $
%D $ a + \fenced[bar][factor=4] {\frac {b} {c}} + d $
%D $ a + \fenced[bar]           {\frac {b} {c}} + d $
%D \stoptyping

% \startbuffer
%     $ \left( \frac{1}{x}^{2} \right)$
%     $ \left( x \right)$
%     $ \left( x^2 \right)$
%     $ \left( \frac{1}{x} \right)$
%     $ \left( \frac{1}{x}^2 \right)$
% \stopbuffer
%
% \getbuffer\blank
% {\setupmathfence[topspace=-2pt,bottomspace=-1pt]\getbuffer\blank}

% todo : class -> number

\newconditional\c_math_fenced_mirror \c_math_fenced_mirror\conditionaltrue
\newconditional\c_math_fenced_sized  \c_math_fenced_sized \conditionalfalse
\newinteger    \c_math_fence_nesting

\installcorenamespace {mathfencesize}

\defcsname\??mathfencesize  big\endcsname{1}
\defcsname\??mathfencesize  Big\endcsname{2}
\defcsname\??mathfencesize bigg\endcsname{3}
\defcsname\??mathfencesize Bigg\endcsname{4}

\let\math_fenced_trace\donothing

\def\math_fenced_common_factor_none % a weird one anyway
  {\Uvextensible
   \s!axis    \relaxedspace
   \s!exact   \relaxedspace
   \s!variant \mathvariantslot\fam \c_math_fence_nesting}
 % \s!variant \mathvariantslot\fam {\c_math_fence_nesting+\plusone}}

\def\math_fenced_common_factor_fixed
  {\Uvextensible
   \s!axis
   \s!exact}

\def\math_fenced_common_factor_unknown
  {\scratchdimen{\p_factor\bodyfontsize/2}%
   \Uvextensible
   \s!height\scratchdimen
   \s!depth \scratchdimen
   \s!axis
   \s!exact}

\def\math_fenced_common_factor_force
  {\Uvextensible
   \s!height{\mathfenceparameter\c!height}%
   \s!depth {\mathfenceparameter\c!depth}%
   \s!axis
   \s!exact}

\def\math_fenced_common_factor_size
  {\Uvextensible
   \math_fenced_set_variant}

\def\math_fenced_common_factor_empty#1%
  {\ifconditional\c_math_fenced_level_mode
     \Uvextensible
   \else
     #1% \Uleft \Umiddle \Uleft
     \ifx#1\Umiddle
       \ifx\p_overflow\v!auto
         \s!middle\relaxedspace
         \s!nooverflow\relaxedspace
       \orelse\ifx\p_overflow\v!no
         \s!nooverflow\relaxedspace
       \fi
     \fi
   \fi}

\def\math_fenced_common_factor_auto#1%
  {\ifconditional\c_math_fenced_level_mode
     \Uvextensible
     \math_fenced_set_variant
   \else
     #1% \Uleft \Umiddle \Uleft
     \math_fenced_set_variant
     \ifx#1\Umiddle
       \ifx\p_overflow\v!auto
         \s!middle\relaxedspace
         \s!nooverflow\relaxedspace
       \orelse\ifx\p_overflow\v!no
         \s!nooverflow\relaxedspace
       \fi
     \fi
   \fi}

% \startTEXpage[offset=1dk]
%     \dm { \fenced[brace][middle="7C] { \frac{p}{q} \fence p,q \in \naturalnumbers} }\par
%     \dm { \fenced[brace][middle=`|]  { \frac{p}{q} \fence p,q \in \naturalnumbers} }\par
%     \dm { \fenced[brace][middle=124] { \frac{p}{q} \fence p,q \in \naturalnumbers} }\par
%     \dm { \fenced[brace][middle=|]   { \frac{p}{q} \fence p,q \in \naturalnumbers} }
% \stopTEXpage

\newconstant\c_math_fenced_class
\newinteger \c_math_fence_check

\integerdef\c_math_factor_fenced\zerocount

\installglobalmacrostack\c_math_factor_fenced

\protected\def\math_fenced_common#1#2#3#4#5% \Uwhatever class symbol source color
  {\c_math_fenced_class\math_class_by_parameter\mathfenceparameter#2%
   \math_fenced_check_size_mismatch % we need to catch an unbalanced \F as we are sequential
   \ifconditional\c_math_fenced_sized
   \orelse\ifconditional\c_math_fenced_level_mode
     \ifnum\c_math_fenced_class=\mathopencode
       \integerdef\c_math_fenced_stack\c_math_fenced_level
       \push_macro_c_math_fenced_stack
     \orelse\ifnum\c_math_fenced_class=\mathclosecode
       \pop_macro_c_math_fenced_stack
       \c_math_fenced_level\c_math_fenced_stack
     \fi
   \fi
   \edef\p_fence{#3}%
   \ifempty\p_fence
     \ifnum\c_math_fenced_class=\mathmiddlecode\else#1.\relax\fi
   \else
     %
     \ifx\p_fence\v!none
       \lettonothing\p_mp
     \orelse\ifcstok{\mathfenceparameter\c!plugin}\v!mp
       \edef\p_mp{\mathfenceparameter\c!mp}%
       \ifempty\p_mp\else
         \clf_set_extensible_data
             mp      {\p_mp}
             unicode \ifchknumber\p_fence\or\lastchknumber\else\expandafter`\p_fence\fi
         \relax
         % much of below is not relevant
       \fi
     \else
       \lettonothing\p_mp
     \fi
     %
     \edef\p_factor      {\mathfenceparameter\c!factor}%
     \edef\p_overflow    {\mathfenceparameter\c!overflow}%
     \edef\p_size        {\mathfenceparameter\c!size}%
     \edef\p_mathclass   {\mathfenceparameter\c!mathclass}%
     \edef\p_inlinefactor{\ifconditional\indisplaymath\mathfenceparameter\c!displayfactor\else\mathfenceparameter\c!inlinefactor\fi}%
     \scratchcounter\math_tags_mfunctionlabattribute\plusthree{\currentglobalmathfence}{\mathfenceparameter\c!mathmeaning}\relax
     \ifempty\p_inlinefactor
       % nothing
     \orelse\ifx#1\Uleft
       \push_macro_c_math_factor_fenced
       \integerdef\c_math_factor_fenced\p_inlinefactor\relax
     \orelse\ifx#1\Uright
       \pop_macro_c_math_factor_fenced
     \fi
     \ifnum\c_math_fenced_level>\zerocount
       \math_fenced_common_factor_fixed
       \math_fenced_set_variant
     \orelse\ifconditional\c_math_fenced_sized
       \math_fenced_common_factor_fixed
     \orelse\ifempty\p_factor
       \math_fenced_common_factor_empty#1%
     \orelse\ifx\p_factor\v!auto
       \math_fenced_common_factor_auto#1%
     \orelse\ifx\p_factor\v!none
       \math_fenced_common_factor_none
     \orelse\ifx\p_factor\v!fixed
       \math_fenced_common_factor_fixed
     \orelse\ifx\p_factor\v!force
       \math_fenced_common_factor_force
     \orelse\ifx\p_factor\v!size
       \math_fenced_common_factor_size
     \else
       \math_fenced_common_factor_unknown
     \fi
     \usedsymbolcolorparameterattributes{\mathfenceparameter#5}%
     \ifcase\scratchcounter\else
       \s!attr \mathcategoryattribute \scratchcounter % will change
     \fi
     \s!class
       \ifx\p_fence\v!none
         \mathghostcode
       \orelse\ifempty\p_mathclass
         \c_math_fenced_class
       \else
         \mathcodechecked\p_mathclass
       \fi
     \s!source {\namedboxanchor{\mathfenceparameter#4}}%
     %
     \ifempty\p_mp\else
       \s!usecallback\relaxedspace
     \fi
     %
     \s!top    \mathfenceparameter\c!topspace
     \s!bottom \mathfenceparameter\c!bottomspace
     %
     \ifzero\c_math_factor_fenced\else
       \s!factor \c_math_factor_fenced
     \fi
     %
     \ifcstok{\mathfenceparameter\c!snap}\v!yes
       \s!single\relaxedspace
     \fi
     %
     \math_fenced_trace
     \ifx\p_fence\v!none
     % todo: test with \nomathchar
       \Umathchar\mathghostcode\fam\zerocount
     \orelse\ifchknumber\p_fence\or
       \Umathchar\mathghostcode\fam\lastchknumber
     \else
       \p_fence
     \fi
   \fi}

\def\math_fenced_set_variant
  {\ifconditional\c_math_fenced_level_mode
     \s!variant \mathvariantslot\fam \c_math_fenced_level
   \orelse\ifempty\p_size
     % nothing
   \orelse\ifcsname\??mathfencesize\p_size\endcsname
     \s!variant \mathvariantslot\fam \numexpr\lastnamedcs\relax
   \orelse\ifcstok{\mathfenceparameter\c!alternative}\v!big
     \s!variant \mathvariantslot\fam {\p_size}%
   \orelse\ifcstok{\lastnamedcs}\v!small
     \s!variant {(\p_size)+\plusone}%
   \fi}

\def\math_fenced_left
  {\advanceby\c_math_fence_nesting\plusone
   \math_fenced_common\Uleft\c!leftclass\math_fenced_p_left\c!leftsource\c!leftcolor}

\def\math_fenced_right
  {\math_fenced_common\Uright\c!rightclass\math_fenced_p_right\c!rightsource\c!rightcolor
   \advanceby\c_math_fence_nesting\minusone}

\def\math_fenced_middle_normal
  {%\beginmathgroup %doesn't work well with color etc
   \math_fenced_common\Umiddle\c!middleclass\math_fenced_p_middle\c!middlesource\c!middlecolor
   }%\endmathgroup}

\def\math_fenced_middle_sized
  {\c_math_fenced_sized\conditionaltrue
   \math_fenced_middle_normal
   \c_math_fenced_sized\conditionalfalse}

\appendtoks
    \let\math_fenced_middle\math_fenced_middle_normal
    \enforced\let\fence\math_fenced_direct
\to \everymathatom

\let\math_fenced_middle\math_fenced_middle_normal

\def\math_fenced_p_left
  {\ifconditional\c_math_fenced_mirror
     \ifconditional\c_math_right_to_left
       \mathfenceparameter\c!right
     \else
       \mathfenceparameter\c!left
     \fi
   \else
     \mathfenceparameter\c!left
   \fi}

\def\math_fenced_p_middle
  {\mathfenceparameter\c!middle}%

\def\math_fenced_p_right
  {\ifconditional\c_math_fenced_mirror
     \ifconditional\c_math_right_to_left
       \mathfenceparameter\c!left
     \else
       \mathfenceparameter\c!right
     \fi
   \else
     \mathfenceparameter\c!right
   \fi}

\aliased\let\fence \relax
\aliased\let\fenced\relax

\protected\def\math_fenced_middle_bar  {\mfence |\relax}
\protected\def\math_fenced_middle_colon{\mfence :\relax}
\protected\def\math_fenced_middle_comma{\mathatom \s!leftclass \mathpunctuationcode \s!rightclass \mathmiddlecode {,}}

\ifdefined\suchthat \else \aliased\let\suchthat\relax \fi
\ifdefined\where    \else \aliased\let\where   \relax \fi
\ifdefined\and      \else \aliased\let\and     \relax \fi

\startsetups math:fence:set:bar
    \enforced\let\suchthat\math_fenced_middle_bar
    \enforced\let\where   \math_fenced_middle_comma
    \enforced\let\and     \math_fenced_middle_comma
\stopsetups

\startsetups math:fence:set:colon
    \enforced\let\suchthat\math_fenced_middle_colon
    \enforced\let\where   \math_fenced_middle_comma
    \enforced\let\and     \math_fenced_middle_comma
\stopsetups

\startsetups math:fence:set
    \directsetup{math:fence:set:bar}
\stopsetups

\mutable\lettonothing\suchthat

% \fastsetup{math:fence:set}

\protected\def\math_fenced_middle_common
  {\math_fenced_middle} % redefined inside atom

\protected\def\math_fenced_fenced_common
  {\startusemathstyleparameter\mathfenceparameter\c!mathstyle
   \usesetupsparameter\mathfenceparameter
   \enforced\let\fence\math_fenced_middle_common}

\protected\def\math_fenced_fenced_start#1%
  {\begingroup
 %{\beginmathgroup
   \cdef\currentmathfence{#1}%
   \math_fenced_fenced_common
   \math_fenced_left}

\protected\def\math_fenced_fenced_stop#1%
  {\cdef\currentmathfence{#1}%
   \math_fenced_right
   \stopusemathstyleparameter
   \endgroup}
  %\endmathgroup}

\installlocalcurrenthandler \??mathfences {mathfence}

%D The horizontal text variant was introduced for Alan Braslau. Because this is not
%D used that often we only support double text arguments.
%D
%D Musical timestamp: I am The Moon by Tedeschi Trucks Band

% \definemathfence [tupdownarrows] [text] [\c!left="2191,\c!right="2193]

\def\math_fenced_check#1%
  {\ifempty{\mathfenceparameter#1}\letmathfenceparameter#1\v!none\fi}

\appendtoks
    \math_fenced_check\c!left
    \math_fenced_check\c!right
\to \everysetupmathfence

\appendtoks
    \math_fenced_check\c!left
    \math_fenced_check\c!right
\to \everydefinemathfence

\protected\def\math_fenced_horizontal_common#1#2#3#4#5% \Uwhatever class symbol source color
  {\c_math_fenced_class\math_class_by_parameter\mathfenceparameter#2\relax
   \edef\p_fence{#3}%
   #1% \Uleft \Umiddle \Uleft
   \usedcolorparameterattributes{\mathfenceparameter#5}%
   \s!leftclass  \mathunspacedcode
   \s!rightclass \mathunspacedcode
   \s!class      \mathunspacedcode
   \s!source     {\namedboxanchor{\mathfenceparameter#4}}%
   \Umathchar\mathghostcode\fam{\p_fence}}

\tolerant\protected\def\math_fenced_horizontal#1#*[#S#2]#:#*#3#4%
  {\mathord \bgroup % class here
     \setlocalmathfencecurrent{#1}% \cdef\currentmathfence{#1}%
     \setupcurrentmathfence[#2]%
   % \usemathstyleparameter\mathfenceparameter\c!mathstyle
     \setmathsmalltextbox\scratchboxone\hbox{\usemathfencestyleandcolor\c!leftstyle \c!leftcolor #3}%
     \setmathsmalltextbox\scratchboxtwo\hbox{\usemathfencestyleandcolor\c!rightstyle\c!rightcolor#4}%
     \let\math_fenced_common\math_fenced_horizontal_common
     \edef\p_middle{\mathfenceparameter\c!middle}%
     \ifempty\p_middle\else
       \letmathfenceparameter\c!left \p_middle
       \letmathfenceparameter\c!right\zerocount
     \fi
     \scratchdistance{\mathfenceparameter\c!distance}%
     \box\scratchboxone
     \kern\scratchdistance
     \math_fenced_fenced_start\currentmathfence
     \math_fenced_fenced_stop \currentmathfence
     \kern\scratchdistance
     \box\scratchboxtwo
   \egroup}

\tolerant\protected\def\math_fenced_fenced#1%
  {\ifcstok{\namedmathfenceparameter{#1}\c!text}\v!yes % not the best keyword
     \expandafter\math_fenced_horizontal
   \else
     \expandafter\math_fenced_vertical
   \fi{#1}}

% two step because we don't want to define text itself as command

\definemathfence
  [\v!text]

\setupmathfence
  [\v!text]
  [\c!text=\v!yes,
   \c!define=\v!yes,
   \c!distance=.125\emwidth]

% \tolerant\protected\def\math_fenced_vertical#1#*[#S#2]%
%   {\begingroup
%  %{\beginmathgroup
%    \setlocalmathfencecurrent{#1}% \cdef\currentmathfence{#1}%
%    \c_math_fenced_level_mode\conditionalfalse
%    \resetmathfenceparameter\c!size
%    \letmathfenceparameter\c!factor\v!auto
%    \ifparameter#2\or
%      \setupcurrentmathfence[#2]%
%    \fi
%    \math_fenced_fenced_common
%    \math_fenced_fenced_indeed_adapt}

% \protected\def\math_fenced_fenced_indeed_adapt#1%
%   {\c_math_fenced_sized\conditionalfalse
%    \math_fenced_left
%    #1%
%    \c_math_fenced_sized\conditionalfalse
%    \math_fenced_right
%    \math_fenced_fenced_indeed_finish}

% \protected\def\math_fenced_fenced_indeed_finish
%   {\stopusemathstyleparameter
%    \endgroup}
%   %\endmathgroup}

\tolerant\protected\def\math_fenced_vertical#1#*[#S#2]#:#3%
 %{\beginmathgroup
  {\begingroup
   \setlocalmathfencecurrent{#1}% \cdef\currentmathfence{#1}%
   \c_math_fenced_level_mode\conditionalfalse
   \resetmathfenceparameter\c!size
   \letmathfenceparameter\c!factor\v!auto
   \ifparameter#2\or
     \setupcurrentmathfence[#2]%
   \fi
   \math_fenced_fenced_common
   \c_math_fenced_sized\conditionalfalse
   \math_fenced_left
   #3%
   \c_math_fenced_sized\conditionalfalse
   \math_fenced_right
   \stopusemathstyleparameter
   \endgroup}
  %\endmathgroup}

\protected\def\math_fenced_direct[#1]%
  {\math_fenced_fenced{#1}}

\appendtoks
    \enforced\let\fenced\math_fenced_direct
% \to \everysetupmathematics
\to \everyswitchmathematics

\permanent\tolerant\protected\def\startmathfenced[#1]#*[#S#2]%
  {\begingroup
   \cdef\currentmathfence{#1}%
   \setupcurrentmathfence[#2]%
   \math_fenced_fenced_start{#1}}

\permanent\protected\def\stopmathfenced
  {\math_fenced_fenced_stop\currentmathfence
   \endgroup}

\lettonothing\m_math_fenced_wrap

\protected\def\math_fenced_start_wrap#1%
  {\begingroup
   \edef\m_math_fenced_wrap{#1}%
   \ifempty\m_math_fenced_wrap \else
     \math_fenced_fenced_start\m_math_fenced_wrap
   \fi}

\protected\def\math_fenced_stop_wrap
  {\ifempty\m_math_fenced_wrap \else
     \math_fenced_fenced_stop\m_math_fenced_wrap
   \fi
   \endgroup}

% for torture testing mikael sundqvist:
%
% \setupmathfence[brace][middle=124]
%
% \im{\fenced[brace]        {\vec{x}\in\reals^3\middle\vert \vec{x}\neq \vec{0}}}
% \im{\fenced[brace]        {\vec{x}\in\reals^3\mid         \vec{x}\neq \vec{0}}}
% \im{\fenced[brace][size=0]{\vec{x}\in\reals^3\fence       \vec{x}\neq \vec{0}}}

\aliased\let\normalmid\mid

\protected\def\mid{\ifcase\c_math_fence_nesting\normalmid\else\middle\vert\fi}

% cases are defined in math-ali:

\definemathfence [cases]   [\c!left="007B,\c!right=\v!none]
\definemathfence [sesac]   [\c!left=\v!none,\c!right="007D]
\definemathfence [tekcarb] [\c!left="005D,\c!right="005B]   % used for xıɹʇɐɯ

%D This is new:
%D
%D \starttyping
%D $ \F0 \left( x + \F1 \left( x \right) + x \right) $
%D $
%D   \F0 \left( x + \F1 \left( x + \F2 \left( x + \F3 \left( x + \F4 \left( x +
%D   2
%D   + x \right) + x \right) + x \right) + x \right) + x \right)
%D $
%D $ \F1 \left( x + \F1 \left( x \right) + x \right) $
%D $ \F3 \left( x + \F1 \left( x \right) + x \right) $
%D $ \F1 \left( x + \F4 \left( x \right) + x \right) $
%D $ \F4 \left( x + \F- \left( x \right) + x \right) $
%D $ \F4
%D     \left( 1 +
%D         \F- \left( 2 +
%D             \F* \left( 3 +
%D                 4
%D             \right)
%D             + 5 +
%D             \F- \left( 6 +
%D                 7
%D             \right)
%D         \right)
%D         + 8
%D     \right)
%D $
%D \stoptyping
%D
%D \starttyping
%D \startTEXpage[offset=1dk,width=20dk]
%D   \ruledhbox{$ \F3 \left( 1 + \F2 \left( a + b \right) + \left( a + b \right) \right) $}\par
%D   \ruledhbox{$ \left( 1 + \F3 \left( a + b \right) + \left( a + b \right) \right) $}\par
%D   \ruledhbox{$ \F3 \left( 1 + \F0 \left( a + b \right) \right) $}\par
%D   \ruledhbox{$ \F3 \left( 1 + \F= \left( a + b \right) \right) $}\par
%D   \ruledhbox{$ \F4 \left( 1 + \fenced[parenthesis]{a + b} \right) $}\par
%D   \ruledhbox{$ \F3 \left( 1 + \F- \left( a + b \right) \right) $}\par
%D   \ruledhbox{$ \left( \frac{1}{1+x} \right) $}\par
%D   \ruledhbox{$ \left( \frac{1}{1+x} \right) $}\par
%D \stopTEXpage
%D \stoptyping

\newinteger    \c_math_fenced_level
\newconditional\c_math_fenced_level_mode

\integerdef\c_math_fenced_stack \zerocount

\installmacrostack \c_math_fenced_stack

\installcorenamespace{fencelevels}
\installcorenamespace{fencestack}

\defcsname\??fencelevels+\endcsname{\advanceby\c_math_fenced_level\plusone  }
\defcsname\??fencelevels-\endcsname{\advanceby\c_math_fenced_level\minusone }
\defcsname\??fencelevels=\endcsname          {\c_math_fenced_level\zerocount}

\letcsname\??fencelevels*\endcsname\donothing

\def\math_fenced_check_size_mismatch
 {\ifnum\c_math_fence_check=\c_math_fence_nesting
    \c_math_fenced_level_mode\conditionalfalse
    \c_math_fenced_level\zerocount
  \fi}

\permanent\protected\def\F#1%
  {\ifconditional\c_math_fenced_level_mode\else
     \c_math_fence_check\c_math_fence_nesting
   \fi
   \c_math_fenced_level_mode\conditionaltrue
   \ifchknum#1\or
     \c_math_fenced_level#1\relax
   \orelse\ifcsname\??fencelevels#1\endcsname
     \lastnamedcs
   \else
     \c_math_fenced_level\zerocount
   \fi}

\definemathfence [parenthesis] [\c!left="0028,\c!right="0029,define=yes]% some kind of meaning
\definemathfence [bracket]     [\c!left="005B,\c!right="005D,define=yes]% some kind of meaning
\definemathfence [brace]       [\c!left="007B,\c!right="007D,define=yes]% some kind of meaning
\definemathfence [bar]         [\c!left="007C,\c!right="007C]
\definemathfence [doublebar]   [\c!left="2016,\c!right="2016]
\definemathfence [triplebar]   [\c!left="2980,\c!right="2980]
\definemathfence [angle]       [\c!left="27E8,\c!right="27E9]
\definemathfence [doubleangle] [\c!left="27EA,\c!right="27EB]
\definemathfence [solidus]     [\c!left="2044,\c!right="2044]
\definemathfence [ceiling]     [\c!left="2308,\c!right="2309,define=yes]% Have meaning
\definemathfence [floor]       [\c!left="230A,\c!right="230B,define=yes]% Have meaning
\definemathfence [moustache]   [\c!left="23B0,\c!right="23B1]
\definemathfence [uppercorner] [\c!left="231C,\c!right="231D]
\definemathfence [lowercorner] [\c!left="231E,\c!right="231F]
\definemathfence [group]       [\c!left="27EE,\c!right="27EF]
\definemathfence [openbracket] [\c!left="27E6,\c!right="27E7]

\definemathfence [nothing]

\definemathfence [mirrored] % \v!mirrored

\definemathfence [mirroredparenthesis] [mirrored] [\c!right="0028,\c!left="0029]
\definemathfence [mirroredbracket]     [mirrored] [\c!right="005B,\c!left="005D]
\definemathfence [mirroredbrace]       [mirrored] [\c!right="007B,\c!left="007D]
\definemathfence [mirroredbar]         [mirrored] [\c!right="007C,\c!left="007C]
\definemathfence [mirroreddoublebar]   [mirrored] [\c!right="2016,\c!left="2016]
\definemathfence [mirroredtriplebar]   [mirrored] [\c!right="2980,\c!left="2980]
\definemathfence [mirroredangle]       [mirrored] [\c!right="27E8,\c!left="27E9]
\definemathfence [mirroreddoubleangle] [mirrored] [\c!right="27EA,\c!left="27EB]
\definemathfence [mirroredsolidus]     [mirrored] [\c!right="2044,\c!left="2044]
\definemathfence [mirroredceiling]     [mirrored] [\c!right="2308,\c!left="2309]
\definemathfence [mirroredfloor]       [mirrored] [\c!right="230A,\c!left="230B]
\definemathfence [mirroredmoustache]   [mirrored] [\c!right="23B0,\c!left="23B1]
\definemathfence [mirroreduppercorner] [mirrored] [\c!right="231C,\c!left="231D]
\definemathfence [mirroredlowercorner] [mirrored] [\c!right="231E,\c!left="231F]
\definemathfence [mirroredgroup]       [mirrored] [\c!right="27EE,\c!left="27EF]
\definemathfence [mirroredopenbracket] [mirrored] [\c!right="27E6,\c!left="27E7]

\definemathfence [mirrorednothing]     [mirrored]

%D A bonus:

\pushoverloadmode

\permanent\protected\def\Lparenthesis         {\math_fenced_fenced_start{parenthesis}}          \immutable\protected\def\Rparenthesis         {\math_fenced_fenced_stop {parenthesis}}
\permanent\protected\def\Lbracket             {\math_fenced_fenced_start{bracket}}              \immutable\protected\def\Rbracket             {\math_fenced_fenced_stop {bracket}}
\permanent\protected\def\Lbrace               {\math_fenced_fenced_start{brace}}                \immutable\protected\def\Rbrace               {\math_fenced_fenced_stop {brace}}
\permanent\protected\def\Langle               {\math_fenced_fenced_start{angle}}                \immutable\protected\def\Rangle               {\math_fenced_fenced_stop {angle}}
\permanent\protected\def\Ldoubleangle         {\math_fenced_fenced_start{doubleangle}}          \immutable\protected\def\Rdoubleangle         {\math_fenced_fenced_stop {doubleangle}}
\permanent\protected\def\Lbar                 {\math_fenced_fenced_start{bar}}                  \immutable\protected\def\Rbar                 {\math_fenced_fenced_stop {bar}}
\permanent\protected\def\Ldoublebar           {\math_fenced_fenced_start{doublebar}}            \immutable\protected\def\Rdoublebar           {\math_fenced_fenced_stop {doublebar}}
\permanent\protected\def\Ltriplebar           {\math_fenced_fenced_start{triplebar}}            \immutable\protected\def\Rtriplebar           {\math_fenced_fenced_stop {triplebar}}
\permanent\protected\def\Lsolidus             {\math_fenced_fenced_start{solidus}}              \immutable\protected\def\Rsolidus             {\math_fenced_fenced_stop {solidus}}
\permanent\protected\def\Lfloor               {\math_fenced_fenced_start{floor}}                \immutable\protected\def\Rfloor               {\math_fenced_fenced_stop {floor}}
\permanent\protected\def\Lceiling             {\math_fenced_fenced_start{ceiling}}              \immutable\protected\def\Rceiling             {\math_fenced_fenced_stop {ceiling}}
\permanent\protected\def\Lmoustache           {\math_fenced_fenced_start{moustache}}            \immutable\protected\def\Rmoustache           {\math_fenced_fenced_stop {moustache}}
\permanent\protected\def\Luppercorner         {\math_fenced_fenced_start{uppercorner}}          \immutable\protected\def\Ruppercorner         {\math_fenced_fenced_stop {uppercorner}}
\permanent\protected\def\Llowercorner         {\math_fenced_fenced_start{lowercorner}}          \immutable\protected\def\Rlowercorner         {\math_fenced_fenced_stop {lowercorner}}
\permanent\protected\def\Lgroup               {\math_fenced_fenced_start{group}}                \immutable\protected\def\Rgroup               {\math_fenced_fenced_stop {group}}
\permanent\protected\def\Lopenbracket         {\math_fenced_fenced_start{openbracket}}          \immutable\protected\def\Ropenbracket         {\math_fenced_fenced_stop {openbracket}}
\permanent\protected\def\Lnothing             {\math_fenced_fenced_start{nothing}}              \immutable\protected\def\Rnothing             {\math_fenced_fenced_stop {nothing}}

\permanent\protected\def\Lparenthesismirrored {\math_fenced_fenced_stop {mirroredparenthesis}}  \immutable\protected\def\Rparenthesismirrored {\math_fenced_fenced_start{mirroredparenthesis}}
\permanent\protected\def\Lbracketmirrored     {\math_fenced_fenced_stop {mirroredbracket}}      \immutable\protected\def\Rbracketmirrored     {\math_fenced_fenced_start{mirroredbracket}}
\permanent\protected\def\Lbracemirrored       {\math_fenced_fenced_stop {mirroredbrace}}        \immutable\protected\def\Rbracemirrored       {\math_fenced_fenced_start{mirroredbrace}}
\permanent\protected\def\Langlemirrored       {\math_fenced_fenced_stop {mirroredangle}}        \immutable\protected\def\Ranglemirrored       {\math_fenced_fenced_start{mirroredangle}}
\permanent\protected\def\Ldoubleanglemirrored {\math_fenced_fenced_stop {mirroreddoubleangle}}  \immutable\protected\def\Rdoubleanglemirrored {\math_fenced_fenced_start{mirroreddoubleangle}}
\permanent\protected\def\Lbarmirrored         {\math_fenced_fenced_stop {mirroredbar}}          \immutable\protected\def\Rbarmirrored         {\math_fenced_fenced_start{mirroredbar}}
\permanent\protected\def\Ldoublebarmirrored   {\math_fenced_fenced_stop {mirroreddoublebar}}    \immutable\protected\def\Rdoublebarmirrored   {\math_fenced_fenced_start{mirroreddoublebar}}
\permanent\protected\def\Ltriplebarmirrored   {\math_fenced_fenced_stop {mirroredtriplebar}}    \immutable\protected\def\Rtriplebarmirrored   {\math_fenced_fenced_start{mirroredtriplebar}}
\permanent\protected\def\Lsolidusmirrored     {\math_fenced_fenced_stop {mirroredsolidus}}      \immutable\protected\def\Rsolidusmirrored     {\math_fenced_fenced_start{mirroredsolidus}}
\permanent\protected\def\Lfloormirrored       {\math_fenced_fenced_stop {mirroredfloor}}        \immutable\protected\def\Rfloormirrored       {\math_fenced_fenced_start{mirroredfloor}}
\permanent\protected\def\Lceilingmirrored     {\math_fenced_fenced_stop {mirroredceiling}}      \immutable\protected\def\Rceilingmirrored     {\math_fenced_fenced_start{mirroredceiling}}
\permanent\protected\def\Lmoustachemirrored   {\math_fenced_fenced_stop {mirroredmoustache}}    \immutable\protected\def\Rmoustachemirrored   {\math_fenced_fenced_start{mirroredmoustache}}
\permanent\protected\def\Luppercornermirrored {\math_fenced_fenced_stop {mirroreduppercorner}}  \immutable\protected\def\Ruppercornermirrored {\math_fenced_fenced_start{mirroreduppercorner}}
\permanent\protected\def\Llowercornermirrored {\math_fenced_fenced_stop {mirroredlowercorner}}  \immutable\protected\def\Rlowercornermirrored {\math_fenced_fenced_start{mirroredlowercorner}}
\permanent\protected\def\Lgroupmirrored       {\math_fenced_fenced_stop {mirroredgroup}}        \immutable\protected\def\Rgroupmirrored       {\math_fenced_fenced_start{mirroredgroup}}
\permanent\protected\def\Lopenbracketmirrored {\math_fenced_fenced_stop {mirroredopenbracket}}  \immutable\protected\def\Ropenbracketmirrored {\math_fenced_fenced_start{mirroredopenbracket}}
\permanent\protected\def\Lnothingmirrored     {\math_fenced_fenced_stop {mirrorednothing}}      \immutable\protected\def\Rnothingmirrored     {\math_fenced_fenced_start{mirrorednothing}}

% These tortoise chars almost only exist in stix (and ar not commonly used)

% \definemathfence [interval]                     [\c!left="2997,\c!right="2998]
% \definemathfence [openinterval]      [interval] [\c!left="2998,\c!right="2998]
% \definemathfence [leftopeninterval]  [interval] [\c!left="2997,\c!right="2997]
% \definemathfence [rightopeninterval] [interval] [\c!left="2998,\c!right="2998]

% Different intervals. The variants are the ones suggested by Bourbaki.

\definemathfence [interval]                        [\c!left="005B,\c!right="005D,define=yes]
\definemathfence [openinterval]         [interval] [\c!left="0028,\c!right="0029,define=yes]
\definemathfence [closedinterval]       [interval] [\c!left="005B,\c!right="005D,define=yes]
\definemathfence [leftopeninterval]     [interval] [\c!left="0028,\c!right="005D,define=yes]
\definemathfence [rightopeninterval]    [interval] [\c!left="005B,\c!right="0029,define=yes]
\definemathfence [varopeninterval]      [interval] [\c!left="005D,\c!right="005B,define=yes]
\definemathfence [varleftopeninterval]  [interval] [\c!left="005D,\c!right="005D,define=yes]
\definemathfence [varrightopeninterval] [interval] [\c!left="005B,\c!right="005B,define=yes]
\definemathfence [integerinterval]      [interval] [\c!left="27E6,\c!right="27E7,define=yes]

\permanent\protected\def\Linterval   {\math_fenced_fenced_start{interval}}
\permanent\protected\def\Lointerval  {\math_fenced_fenced_start{openinterval}}
\permanent\protected\def\Llointerval {\math_fenced_fenced_start{leftopeninterval}}
\permanent\protected\def\Lrointerval {\math_fenced_fenced_start{rightopeninterval}}

\permanent\protected\def\Rinterval   {\math_fenced_fenced_stop {interval}}
\permanent\protected\def\Rointerval  {\math_fenced_fenced_stop {openinterval}}
\permanent\protected\def\Rlointerval {\math_fenced_fenced_stop {leftopeninterval}}
\permanent\protected\def\Rrointerval {\math_fenced_fenced_stop {rightopeninterval}}

% \startformula
% \left{ \frac{1}{a} \right}
% \left[ \frac{1}{b} \right]
% \left( \frac{1}{c} \right)
% \left< \frac{1}{d} \right>
% \left| \frac{1}{e} \right|
% \stopformula

\popoverloadmode

\installcorenamespace{mathleft}
\installcorenamespace{mathright}
\installcorenamespace{mathmiddle}

\pushoverloadmode

% \protected\def\left  {\afterassignment\math_left  \let\nexttoken}
% \protected\def\right {\afterassignment\math_right \let\nexttoken}
% \protected\def\middle{\afterassignment\math_middle\let\nexttoken}

% \im { \left{       \frac{1}{2} \right}       }
% \im { \left\bgroup \frac{1}{2} \right\egroup }
% \im { \left\{      \frac{1}{2} \right\}      }
% \im { \left\lbrace \frac{1}{2} \right\rbrace }

\lettonothing\math_fenced_x_p_left
\lettonothing\math_fenced_x_p_right
\lettonothing\math_fenced_x_p_middle

\def\math_fenced_x_left
  {\advanceby\c_math_fence_nesting\plusone
   \ifx\math_fenced_x_p_left\bgroup\let\math_fenced_x_p_left\letterleftbrace\fi
   \math_fenced_common\Uleft\c!leftclass\math_fenced_x_p_left\c!leftsource\c!leftcolor}

\def\math_fenced_x_right
  {\ifx\math_fenced_x_p_right\egroup\let\math_fenced_x_p_right\letterrightbrace\fi
   \math_fenced_common\Uright\c!rightclass\math_fenced_x_p_right\c!rightsource\c!rightcolor
   \advanceby\c_math_fence_nesting\minusone}

\def\math_fenced_x_middle
  {%\beginmathgroup %doesn't work well with color etc
   \math_fenced_common\Umiddle\c!middleclass\math_fenced_x_p_middle\c!middlesource\c!middlecolor
   }%\endmathgroup}

% the expandafter permits \left\tocharacter...

\permanent\protected\def\lfence{\afterassignment\math_fenced_x_left  \expandafter\let\expandafter\math_fenced_x_p_left}
\permanent\protected\def\rfence{\afterassignment\math_fenced_x_right \expandafter\let\expandafter\math_fenced_x_p_right}
\permanent\protected\def\mfence{\afterassignment\math_fenced_x_middle\expandafter\let\expandafter\math_fenced_x_p_middle}

% These are often used so we provide them:

\aliased\let\left  \lfence
\aliased\let\right \rfence
\aliased\let\middle\mfence

\popoverloadmode

% \let\leftorright\relax

\newconditional\c_math_fenced_unknown  \c_math_fenced_unknown\conditionaltrue

% \permanent\protected\def\installmathfencepair#1#2#3#4%
%   {\letcsname\??mathleft \normalmeaningless#1\endcsname#2%
%    \letcsname\??mathright\normalmeaningless#3\endcsname#4}

\permanent\protected\def\installmathfencepair#1#2#3#4%
  {}

% \def\math_unknown_left  {\ifconditional\c_math_fenced_unknown\Uleft              \nexttoken\fi}
% \def\math_unknown_right {\ifconditional\c_math_fenced_unknown\Uright             \nexttoken\fi}
% \def\math_unknown_middle{\ifconditional\c_math_fenced_unknown\Umiddle nooverflow \nexttoken\fi}

% \def\math_unknown_left
%   {\let\math_fenced_p_left\nexttoken
%    \math_fenced_left}
%
% \def\math_unknown_right
%   {\let\math_fenced_p_right\nexttoken
%    \math_fenced_right}
%
% \def\math_unknown_middle
%   {\let\math_fenced_p_middle\nexttoken
%    \math_fenced_middle}
%
% \letcsname\??mathleft  \s!unknown\endcsname\math_unknown_left
% \letcsname\??mathright \s!unknown\endcsname\math_unknown_right
% \letcsname\??mathmiddle\s!unknown\endcsname\math_unknown_middle
%
% \def\math_left
%   {\ifcsname\??mathleft\normalmeaningless\nexttoken\endcsname
%      \expandafter\lastnamedcs
%    \else
%      \expandafter\math_unknown_left
%    \fi}
%
% \def\math_right
%   {\ifcsname\??mathright\normalmeaningless\nexttoken\endcsname
%      \expandafter\lastnamedcs
%    \else
%      \expandafter\math_unknown_right
%    \fi}
%
% \def\math_middle
%   {\ifcsname\??mathmiddle\normalmeaningless\nexttoken\endcsname
%      \expandafter\lastnamedcs
%    \else
%      \expandafter\math_unknown_middle
%    \fi}
%
% \permanent\protected\def\lfence#1%
%   {\let\nexttoken#1%
%    \ifcsname\??mathleft\normalmeaningless\nexttoken\endcsname
%      \expandafter\lastnamedcs
%    \else
%      \expandafter\math_unknown_left
%    \fi}
%
% \permanent\protected\def\rfence#1%
%   {\let\nexttoken#1%
%    \ifcsname\??mathright\normalmeaningless\nexttoken\endcsname
%      \expandafter\lastnamedcs
%    \else
%      \expandafter\math_unknown_right
%    \fi}
%
% \permanent\protected\def\mfence#1%
%   {\let\nexttoken#1%
%    \ifcsname\??mathmiddle\normalmeaningless\nexttoken\endcsname
%      \expandafter\lastnamedcs
%    \else
%      \expandafter\math_unknown_middle
%    \fi}

% \expanded{\installmathfencepair {|\detokenize {|}} \Ldoublebar {|\detokenize {|}} \Rdoublebar}
% \expanded{\installmathfencepair {|\detokenize{||}} \Ltriplebar {|\detokenize{||}} \Rtriplebar}
%
% \installmathfencepair \bgroup \Lbrace         \egroup \Rbrace
% \installmathfencepair \egroup \Rbracemirrored \bgroup \Lbracemirrored
%
% \installmathfencepair \letteropenbrace \Lbrace \letterclosebrace \Rbrace % as we escape in mp textexts
%
% \installmathfencepair . \Lnothing             . \Rnothing
% \installmathfencepair . \Rnothingmirrored     . \Lnothingmirrored
%
% \installmathfencepair [ \Lbracket             ] \Rbracket
% \installmathfencepair ] \Rbracketmirrored     [ \Lbracketmirrored
%
% \installmathfencepair ( \Lparenthesis         ) \Rparenthesis
% \installmathfencepair ) \Rparenthesismirrored ( \Lparenthesismirrored
%
% \installmathfencepair < \Langle               > \Rangle
% \installmathfencepair > \Ranglemirrored       < \Langlemirrored
%
% \installmathfencepair / \Lsolidus             / \Rsolidus
% %installmathfencepair / \Rsolidusmirrored     / \Lsolidusmirrored
%
% \installmathfencepair | \Lbar                 | \Rbar
% %installmathfencepair | \Rbarmirrored         | \Lbarmirrored
%
% \installmathfencepair ⌊ \Lfloor               ⌋ \Rfloor
% \installmathfencepair ⌋ \Rfloormirrored       ⌊ \Lfloormirrored
% \installmathfencepair ⌈ \Lceiling             ⌉ \Rceiling
% \installmathfencepair ⌉ \Rceilingmirrored     ⌈ \Lceilingmirrored
%
% \installmathfencepair ⟨ \Langle               ⟩ \Rangle
% \installmathfencepair ⟩ \Ranglemirrored       ⟨ \Langlemirrored
%
% \installmathfencepair ⟪ \Ldoubleangle         ⟫ \Rdoubleangle
% \installmathfencepair ⟫ \Rdoubleanglemirrored ⟪ \Ldoubleanglemirrored
%
% \installmathfencepair ‖ \Ldoublebar           ‖ \Rdoublebar
% %installmathfencepair ‖ \Rdoublebarmirrored   ‖ \Ldoublebarmirrored
%
% \installmathfencepair ⦀ \Ltriplebar           ⦀ \Rtriplebar
% %installmathfencepair ⦀ \Rtriplebarmirrored   ⦀ \Ltriplebarmirrored
%
% % \installmathfencepair { \Lbrace             } \Rbrace
% % \installmathfencepair } \Rbracemirrored     { \Lbracemirrored
%
% \installmathfencepair ⦗ \Linterval            ⦘ \Rinterval

% \appendtoks
%     \ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox
% \to \everysetupmathematics
% \to \everyswitchmathematics

% We unofficial support some synonyms as we need them for some fuzzy web related math.

% The names in char-def.lua (historic mess):

\pushoverloadmode

\aliased\let\lbrack      \lbracket
\aliased\let\rbrack      \rbracket
\aliased\let\lceiling    \lceil
\aliased\let\rceiling    \rceil
\aliased\let\lparenthesis\lparent
\aliased\let\rparenthesis\rparent
\aliased\let\lparen      \lparent
\aliased\let\rparen      \rparent

% Just defined:

\aliased\let\Lceil  \Lceiling
\aliased\let\Rceil  \Rceiling
\aliased\let\Lparent\Lparenthesis
\aliased\let\Rparent\Rparenthesis
\aliased\let\Lparen \Lparenthesis
\aliased\let\Rparen \Rparenthesis

% \installmathfencepair \lbrace       \Lbrace       \rbrace       \Rbrace
% \installmathfencepair \lbracket     \Lbracket     \rbracket     \Rbracket
% \installmathfencepair \lbrack       \Lbracket     \rbracket     \Rbracket
% \installmathfencepair \lparenthesis \Lparenthesis \rparenthesis \Rparenthesis
% \installmathfencepair \lparent      \Lparenthesis \rparent      \Rparenthesis
% \installmathfencepair \lparen       \Lparenthesis \rparen       \Rparenthesis
% \installmathfencepair \langle       \Langle       \rangle       \Rangle
% \installmathfencepair \llangle      \Ldoubleangle \rrangle      \Rdoubleangle
% %installmathfencepair \lbar         \Lbar         \rbar         \Rbar
% \installmathfencepair \lVert        \Ldoublebar   \rVert        \Rdoublebar
% \installmathfencepair \vert         \Lbar         \vert         \Rbar
% \installmathfencepair \solidus      \Lsolidus     \solidus      \Rsolidus
% \installmathfencepair \lfloor       \Lfloor       \rfloor       \Rfloor
% \installmathfencepair \lceiling     \Lceiling     \rceiling     \Rceiling
% \installmathfencepair \lceil        \Lceiling     \rceil        \Rceiling

% \installmathfencepair \ulcorner     \Luppercorner \urcorner     \Ruppercorner
% \installmathfencepair \llcorner     \Llowercorner \lrcorner     \Rlowercorner
% \installmathfencepair \lmoustache   \Lmoustache   \rmoustache   \Rmoustache
% \installmathfencepair \llbracket    \Lopenbracket \rrbracket    \Ropenbracket
% \installmathfencepair \lgroup       \Lgroup       \rgroup       \Rgroup

% \installmathfencepair \linterval    \Linterval    \rinterval    \Rinterval
% %installmathfencepair \linterv      \Linterval    \rinterv      \Rinterval
% \installmathfencepair \lointerval   \Linterval    \rointerval   \Rinterval
% \installmathfencepair \llointerval  \Llointerval  \rlointerval  \Rlointerval
% \installmathfencepair \lrointerval  \Lrointerval  \rrointerval  \Rrointerval

\aliased\let\textlbar\lbar \aliased\let\mathlbar\Lbar
\aliased\let\textrbar\lbar \aliased\let\mathrbar\Rbar

\permanent\protected\def\lbar{\mathortext\mathlbar\textlbar}
\permanent\protected\def\rbar{\mathortext\mathrbar\textrbar}

% \setupmathfences[color=darkgreen]

% \permanent\protected\def\{{\mathortext\lbrace      \letterleftbrace       } % or maybe a chardef
% \permanent\protected\def\}{\mathortext\rbrace      \letterrightbrace      } % or maybe a chardef
% \permanent\protected\def\[{\mathortext\lbracket    \letterleftbracket     } % or maybe a chardef
% \permanent\protected\def\]{\mathortext\rbracket    \letterrightbracket    } % or maybe a chardef
% \permanent\protected\def\({\mathortext\lparenthesis\letterleftparenthesis } % or maybe a chardef
% \permanent\protected\def\){\mathortext\rparenthesis\letterrightparenthesis} % or maybe a chardef
% \permanent\protected\def\|{\mathortext\vert        \letterbar             } % or maybe a chardef
% %permanent\protected\def\/{\mathortext\solidus     \letterslash           } % or maybe a chardef
%
% \installmathfencepair \{ \Lbrace        \} \Rbrace
% \installmathfencepair \[ \Lbracket      \] \Rbracket
% \installmathfencepair \( \Lparenthesis  \) \Rparenthesis
% \installmathfencepair \< \Langle        \> \Rangle
% \installmathfencepair \| \Lbar          \| \Rbar

% isn't that already the case .. still needed in lua mode ?

\aliased\let\{\letterleftbrace
\aliased\let\}\letterrightbrace
\aliased\let\[\letterleftbracket
\aliased\let\]\letterrightbracket
\aliased\let\(\letterleftparenthesis
\aliased\let\)\letterrightparenthesis
\aliased\let\|\letterbar
%aliased\let\/\letterslash % italic correction

\popoverloadmode

%D As we have overloaded \type {\left} and \type {\right} we also need a more
%D clever version of the following:

% alternatives:
%
% small: step 1
% big  : take step from lfg

\permanent\protected\def\choosemathbig
  {\mathortext\math_choosemathbig_math\math_choosemathbig_text}

\protected\def\math_choosemathbig_math#1#2% so we accept \big{||} as well
  {\begingroup
   \edef\p_size{#1}%
   \Uvextensible
     \s!axis
     \s!exact
     \math_fenced_set_variant
     #2%
   \relax
   \endgroup}

\protected\def\math_choosemathbig_text#1#2% so we accept \big{||} as well
  {\naturalhbox\bgroup
      \startimath
        \math_choosemathbig_math{#1}{#2}%
        \nulldelimiterspace\zeropoint
        \mathsurround\zeropoint
      \stopimath
    \egroup}

\permanent\protected\def\mathdelimiterstep#1#2% not used, only in example
  {\Uvextensible
     \s!axis
     \s!exact
     \s!variant {#1}% always from original sizes not lfg
     #2%
   \relax}

\definemathcommand [big]  {\choosemathbig1}
\definemathcommand [Big]  {\choosemathbig2}
\definemathcommand [bigg] {\choosemathbig3}
\definemathcommand [Bigg] {\choosemathbig4}

\definemathcommand [bigl]  [\s!open]     [one] {\big}
\definemathcommand [bigm]  [\s!relation] [one] {\big}    % why not just middle
\definemathcommand [bigr]  [\s!close]    [one] {\big}
\definemathcommand [Bigl]  [\s!open]     [one] {\Big}
\definemathcommand [Bigm]  [\s!relation] [one] {\Big}
\definemathcommand [Bigr]  [\s!close]    [one] {\Big}
\definemathcommand [biggl] [\s!open]     [one] {\bigg}
\definemathcommand [biggm] [\s!relation] [one] {\bigg}
\definemathcommand [biggr] [\s!close]    [one] {\bigg}
\definemathcommand [Biggl] [\s!open]     [one] {\Bigg}
\definemathcommand [Biggm] [\s!relation] [one] {\Bigg}
\definemathcommand [Biggr] [\s!close]    [one] {\Bigg}

% \definemathfence [integral] [\c!left="222B]
%
% \protected\def\Lintegral  {\math_fenced_fenced_start{integral}}
% \protected\def\Rintegral  {\math_fenced_fenced_stop {integral}}
%
% \installmathfencepair \lintegral \Lintegral \rintegral \Rintegral
%
% \left\lintegral
%     \vrule height 3cm depth 3cm
% \right\rintegral

%definemathfence [fancybracket] [bracket] [define=yes,color=red]

%D The nested fences recovery code is needed for mathml and the original
%D code can still be found in the mkiv file.

\definesystemattribute[mathautofence][public]

\let\math_fences_normal_left  \left
\let\math_fences_normal_right \right
\let\math_fences_normal_middle\middle
\let\math_fences_normal_both  \relax  % undefined

\protected\def\math_fences_auto_left  #1{\c_attr_mathautofence\plusone  #1\c_attr_mathautofence\attributeunsetvalue}
\protected\def\math_fences_auto_right #1{\c_attr_mathautofence\plustwo  #1\c_attr_mathautofence\attributeunsetvalue}
\protected\def\math_fences_auto_middle#1{\c_attr_mathautofence\plusthree#1\c_attr_mathautofence\attributeunsetvalue}
\protected\def\math_fences_auto_both  #1{\c_attr_mathautofence\plusfour #1\c_attr_mathautofence\attributeunsetvalue}

\permanent\let\autofenceopen  \math_fences_auto_left    % for testing
\permanent\let\autofenceclose \math_fences_auto_right   % for testing
\permanent\let\autofenceleft  \math_fences_auto_left    % for testing
\permanent\let\autofenceright \math_fences_auto_right   % for testing
\permanent\let\autofencemiddle\math_fences_auto_middle  % for testing
\permanent\let\autofenceboth  \math_fences_auto_both    % for testing

% fences are used not that often (i.e. no performance issue) so we can use a state
% instead of \let ... also some state variable can come in handy in the future

\newconditional\c_math_fences_auto

\permanent\protected\def\enableautofences
  {\clf_enableautofences
   \c_math_fences_auto\conditionalfalse
   \glet\clf_enableautofences\relax % onlyonce anyway
   \enforced\permanent\protected\gdef\enableautofences{\c_math_fences_auto\conditionaltrue}%
   \enableautofences}

\permanent\protected\def\disableautofences
  {\c_math_fences_auto\conditionalfalse}

\permanent\protected\def\math_fences_used_left
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_left
   \else
     \expandafter\math_fences_normal_left
   \fi}

\permanent\protected\def\math_fences_used_right
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_right
   \else
     \expandafter\math_fences_normal_right
   \fi}

\permanent\protected\def\math_fences_used_middle
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_middle
   \else
     \expandafter\math_fences_normal_middle
   \fi}

\permanent\protected\def\math_fences_used_both
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_both
   \else
     \expandafter\math_fences_normal_both
   \fi}

\aliased\let\left       \math_fences_used_left
\aliased\let\right      \math_fences_used_right
\aliased\let\middle     \math_fences_used_middle
\aliased\let\leftorright\math_fences_used_both

% wrappers

\permanent\protected\def\startcheckedfences
  {\begingroup
   \enableautofences}

\permanent\protected\def\stopcheckedfences
  {\endgroup}

\appendtoks
    \ifempty\currentmathfence
        \ifcstok{\mathfenceparameter\c!state}\v!auto\enableautofences\else\disableautofences\fi
    \fi
\to \everysetupmathfence

\permanent\protected\def\enableautofencemode {\mathcheckfencesmode\plusone}
\permanent\protected\def\disableautofencemode{\mathcheckfencesmode\zerocount}

\appendtoks
    \ifempty\currentmathfence
        \ifcstok{\mathfenceparameter\c!method}\v!auto\enableautofencemode\else\disableautofencemode\fi
    \fi
\to \everysetupmathfence

% some day default: \setupmathfences[\c!state=\v!auto]

%D The next characters were used for constructing nicer extensibles but
%D nowadays we have real characters.

\permanent\Umathchardef\braceld\zerocount \zerocount "FF07A
\permanent\Umathchardef\bracerd\zerocount \zerocount "FF07B
\permanent\Umathchardef\bracelu\zerocount \zerocount "FF07C
\permanent\Umathchardef\braceru\zerocount \zerocount "FF07D

%D Some tracing:

\definefont[mathindexfont][Mono sa .2]

\def\math_fenced_trace_indeed
  {%
   \beginlocalcontrol
     \registerboxanchor
     \registeranchorbox
       \registeredboxanchor
       \plusone
       \hbox
          \s!anchors \boxanchorpresetcode{depth} \boxanchorpresetcode{height}
          \s!yoffset -.1\exheight
          \s!target  \registeredboxanchor
          \s!to      \zeropoint
          {\darkblue\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting}\hss}%
   \endlocalcontrol
   \s!source \registeredboxanchor
   }

% \def\math_fenced_trace_indeed
%   {%
%    \beginlocalcontrol
%      \registerboxanchor
%      \registeranchorbox
%        \registeredboxanchor
%        \plusone
%        \ruledhbox
%           \s!anchors \boxanchorpresetcode{depth} \boxanchorpresetcode{height}
%           \s!yoffset -.1\exheight
%           \s!target \registeredboxanchor
%           \s!to \zeropoint
%           {\darkblue\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting B}\hss}%
%      \registeranchorbox
%        \registeredboxanchor
%        \plusone
%        \ruledhbox
%           \s!anchors \boxanchorpresetcode{height} \boxanchorpresetcode{depth}
%           \s!yoffset .1\exheight
%           \s!target \registeredboxanchor
%           \s!to \zeropoint
%           {\darkgreen\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting T}\hss}%
%      \registeranchorbox
%        \registeredboxanchor
%        \plusone
%        \ruledhbox
%           \s!anchors \boxanchorpresetcode{left} \boxanchorpresetcode{right}
%           \s!xoffset -.1\emwidth
%           \s!target \registeredboxanchor
%           \s!to \zeropoint
%           {\darkred\hss\mathindexfont\ruledhbox{\the\c_math_fence_nesting L}}%
%      \registeranchorbox
%        \registeredboxanchor
%        \plusone
%        \ruledhbox
%           \s!anchors \boxanchorpresetcode{right} \boxanchorpresetcode{left}
%           \s!xoffset .1\emwidth
%           \s!target \registeredboxanchor
%           \s!to \zeropoint
%           {\darkyellow\mathindexfont\ruledhbox{\the\c_math_fence_nesting R}\hss}%
%    \endlocalcontrol
%    \s!source \registeredboxanchor
%    }

\installtextracker
   {math.fencenesting}
   {\let\math_fenced_trace\math_fenced_trace_indeed}
   {\let\math_fenced_trace\donothing}

% \permanent\mutable\integerdef\c_math_fence_level\minusone

\appendtoks
    %c_math_fence_level\minusone
    \c_math_fence_nesting\zerocount
%to \everysetupmathematics
\to \everyswitchmathematics

%D Experiment (needs an interface i.e. key/value), bars are not middle so are not
%D affected but \type {\mvert} is.

\permanent\protected\def\autofences
  {\setmathoptions\mathopencode\numexpression
     \setmathoptions\mathopencode bor \autoinjectclassoptioncode
   \relax
   \setmathoptions\mathclosecode\numexpression
     \setmathoptions\mathclosecode bor \autoinjectclassoptioncode
   \relax
   \setmathoptions\mathmiddlecode\numexpression
     \setmathoptions\mathmiddlecode bor \autoinjectclassoptioncode
   \relax}

%D New (to be completed):

% $x + \tupdownarrows{left}{right} + x$
% $x + \tdownuparrows{left}{right} + x$
% $x + \tupanddownarrows[color=red,leftcolor=green,rightcolor=blue]{left}{right} + x$

\definemathfence [tupanddownarrows][\v!text][\c!left="2191,\c!right="2193]
\definemathfence [tupdownarrows]   [\v!text][\c!left="21C5,\c!right=0]
\definemathfence [tdownuparrows]   [\v!text][\c!middle="21F5]
\definemathfence [tuparrow]        [\v!text][\c!middle="2191]
\definemathfence [tdownarrow]      [\v!text][\c!middle="2193]

% A few meaningful definitions
\definemathfence [abs]         [bar]        [define=yes]
\definemathfence [innerproduct][angle]      [define=yes,middle=`|]
\definemathfence [integerpart] [bracket]    [define=yes]
\definemathfence [norm]        [doublebar]  [define=yes]
\definemathfence [set]         [brace]      [define=yes,middle=`|]
\definemathfence [sequence]    [parenthesis][define=yes]
\definemathfence [tuple]       [parenthesis][define=yes]

\protect
