math-fen.mkiv / last modification: 2020-01-30 14:16
%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

% maybe always "method=auto" for:
%
% \switchtobodyfont[cambria]
% \ruledhbox{$f(x)$}
% \ruledhbox{\mathdelimitersmode6$f\left(x\right)$}
% \ruledhbox{\mathdelimitersmode7$f\left(x\right)$}
% \ruledhbox{$f\left(\frac{1}{x}\right)$}

% todo: mathstyle

% \definemathfence [fancybracket] [bracket] [command=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

\let\setupmathfences\setupmathfence

\setupmathfences
  [\c!method=, % maybe always \v!auto
   \c!left=,
   \c!right=,
   \c!middle=,
   \c!mathstyle=,
   \c!color=,
   \c!command=,
   \c!mathclass=,
   \c!factor=\v!auto]

\appendtoks
    \edef\p_command{\mathfenceparameter\c!command}%
    \ifx\p_command\v!yes
        \setuevalue\currentmathfence{\math_fenced_fenced[\currentmathfence]}%
    \fi
\to \everydefinemathfence

% we need the direct use of \Udelimiter because of { etc

\newconditional\c_math_fenced_mirror \settrue \c_math_fenced_mirror
\newconditional\c_math_fenced_sized  \setfalse\c_math_fenced_sized

\unexpanded\def\math_fenced_inject#1#2#3#4%
  {\ifx#1\empty
     #2.%
   \else
     \edef\p_mathclass{\mathfenceparameter\c!mathclass}%
     \ifconditional\c_math_fenced_sized
       \let\p_factor\v!fixed
     \else
       \edef\p_factor{\mathfenceparameter\c!factor}%
     \fi
     \ifx\p_factor\empty
       \ifx\p_mathclass\empty
         #2%
       \else
         #3%
         \s!class\p_mathclass
       \fi
     \else\ifx\p_factor\v!auto
       \ifx\p_mathclass\empty
         #2%
       \else
         #3%
         \s!class\p_mathclass
       \fi
     \else\ifx\p_factor\v!none
       #3%
       \s!height\zeropoint
       \s!depth\zeropoint
       \ifx\p_mathclass\empty\else
         \s!class\p_mathclass
       \fi
       \s!axis
     % #2%
     \else
       \ifx\p_factor\v!fixed
          \scratchdimen\scaledpoint
       \else
          \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax
       \fi
       #3%
       \s!height\scratchdimen
       \s!depth\scratchdimen
       \ifx\p_mathclass\empty\else
         \s!class\p_mathclass
       \fi
       \s!axis
     \fi\fi\fi
     \Udelimiter#4\fam#1\relax
   \fi}

\def\math_fenced_left
  {\edef\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}%
   \math_fenced_color_push
   \math_fenced_inject\p_left\normalleft\Uleft\plusfour
   \math_fenced_color_pop}

\def\math_fenced_middle
  {\edef\p_middle
     {\mathfenceparameter\c!middle}%
   \mskip\thinmuskip
   \math_fenced_color_push
   \math_fenced_inject\p_middle\normalmiddle\Umiddle\plusfour
   \math_fenced_color_pop
   \mskip\thinmuskip}

\def\math_fenced_right
  {\edef\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}%
   \math_fenced_color_push
   \math_fenced_inject\p_right\normalright\Uright\plusfive
   \math_fenced_color_pop}

\def\math_fenced_color_do_push{\pushcolor[\p_math_fenced_color]}
\let\math_fenced_color_do_pop  \popcolor

\let\math_fenced_color_push\donothing
\let\math_fenced_color_pop \donothing

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

\newcount\c_math_fenced_nesting

\unexpanded\def\math_fenced_fenced_common
  {\startusemathstyleparameter\mathfenceparameter
   \let\fence\math_fenced_middle
   \edef\p_math_fenced_color{\mathfenceparameter\c!color}%
   \ifx\p_math_fenced_color\empty
     \let\math_fenced_color_push\donothing
     \let\math_fenced_color_pop \donothing
   \else
     \let\math_fenced_color_push\math_fenced_color_do_push
     \let\math_fenced_color_pop \math_fenced_color_do_pop
   \fi}

\unexpanded\def\math_fenced_fenced_start#1%
  {\advance\c_math_fenced_nesting\plusone
   \begingroup
   \edef\currentmathfence{#1}%
   \math_fenced_fenced_common
   \math_fenced_left}

\unexpanded\def\math_fenced_fenced_stop#1%
  {\edef\currentmathfence{#1}%
   \math_fenced_right
   \stopusemathstyleparameter
   \endgroup
   \advance\c_math_fenced_nesting\minusone}

\unexpanded\def\math_fenced_fenced[#1]%
  {\advance\c_math_fenced_nesting\plusone
   \begingroup
   \edef\currentmathfence{#1}%
   \dosingleempty\math_fenced_fenced_indeed}

\def\math_fenced_force_size#1#2%
  {\attribute\mathsizeattribute\numexpr#1*\plushundred+#2\relax}

% \unexpanded\def\math_fenced_fenced_indeed[#1]#2%
%   {\iffirstargument\setupcurrentmathfence[#1]\fi
%    \math_fenced_fenced_common
%    \edef\p_size{\mathfenceparameter\c!size}%
%    \ifx\p_size\empty
%       \setfalse\c_math_fenced_sized
%    \else
%       \settrue\c_math_fenced_sized
%       \math_fenced_force_size\bigmathdelimitervariant\p_size
%    \fi
%    \math_fenced_left
%    #2%
%    \math_fenced_right
%    \stopusemathstyleparameter
%    \endgroup
%    \advance\c_math_fenced_nesting\minusone}

\unexpanded\def\math_fenced_fenced_indeed[#1]%
  {\iffirstargument\setupcurrentmathfence[#1]\fi
   \math_fenced_fenced_common
   \edef\p_size{\mathfenceparameter\c!size}%
   \ifx\p_size\empty
     \expandafter\math_fenced_fenced_indeed_adapt
   \else
     \expandafter\math_fenced_fenced_indeed_fixed
   \fi}

\unexpanded\def\math_fenced_fenced_indeed_finish
  {\stopusemathstyleparameter
   \endgroup
   \advance\c_math_fenced_nesting\minusone}

\unexpanded\def\math_fenced_fenced_indeed_fixed#1%
  {\math_fenced_force_size\bigmathdelimitervariant\p_size
   \settrue\c_math_fenced_sized
   \math_fenced_left
   \setfalse\c_math_fenced_sized
   #1%
   \settrue\c_math_fenced_sized
   \math_fenced_right
   \setfalse\c_math_fenced_sized
   \math_fenced_fenced_indeed_finish}

\unexpanded\def\math_fenced_fenced_indeed_adapt#1%
  {\setfalse\c_math_fenced_sized
   \math_fenced_left
   #1%
   \setfalse\c_math_fenced_sized
   \math_fenced_right
   \math_fenced_fenced_indeed_finish}

\appendtoks
    \let\fenced\math_fenced_fenced
\to \everymathematics

% todo: | in mathmode letter
%
% \appendtoks
%     \let\bar\letterbar
% \to \everymathematics
%
% but then we don't have it in embedded text too so ...

\definemathfence [parenthesis] [\c!left="0028,\c!right="0029]
\definemathfence [bracket]     [\c!left="005B,\c!right="005D]
\definemathfence [brace]       [\c!left="007B,\c!right="007D]
\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]
\definemathfence [floor]       [\c!left="230A,\c!right="230B]
\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:

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

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

\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]

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

\unexpanded\def\Rinterval            {\math_fenced_fenced_stop {interval}}
\unexpanded\def\Rointerval           {\math_fenced_fenced_stop {openinterval}}
\unexpanded\def\Rlointerval          {\math_fenced_fenced_stop {leftopeninterval}}
\unexpanded\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

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

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

\let\leftorright\relax

\newconditional\c_math_fenced_done
\newconditional\c_math_fenced_unknown  \settrue\c_math_fenced_unknown

% maybe use \detokenize ... todo \lastnamedcs

% \setvalue{\??mathleft  \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft  \nexttoken\fi}
% \setvalue{\??mathright \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
% \setvalue{\??mathmiddle\s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}
%
% \def\math_left
%   {\settrue\c_math_fenced_done
%    \edef\m_math_left{\normalmeaning\nexttoken}%
%    \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
%
% \def\math_right
%   {\settrue\c_math_fenced_done
%    \edef\m_math_right{\normalmeaning\nexttoken}%
%    \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
%
% \def\math_middle
%   {\settrue\c_math_fenced_done
%    \edef\m_math_middle{\normalmeaning\nexttoken}%
%    \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
%
% \unexpanded\def\lfence#1%
%   {\settrue\c_math_fenced_done
%    \let\nexttoken#1%
%    \edef\m_math_left{\normalmeaning#1}%
%    \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
%
% \unexpanded\def\rfence#1%
%   {\settrue\c_math_fenced_done
%    \let\nexttoken#1%
%    \edef\m_math_right{\normalmeaning#1}%
%    \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
%
% \unexpanded\def\mfence#1%
%   {\settrue\c_math_fenced_done
%    \let\nexttoken#1%
%    \edef\m_math_middle{\normalmeaning#1}%
%    \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}

\unexpanded\def\installmathfencepair#1#2#3#4%
  {\expandafter\let\csname\??mathleft \normalmeaning#1\endcsname#2%
   \expandafter\let\csname\??mathright\normalmeaning#3\endcsname#4}

\def\math_unknown_left  {\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft  \nexttoken\fi}
\def\math_unknown_right {\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
\def\math_unknown_middle{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}

\letvalue{\??mathleft  \s!unknown}\math_unknown_left
\letvalue{\??mathright \s!unknown}\math_unknown_right
\letvalue{\??mathmiddle\s!unknown}\math_unknown_middle

\def\math_left
  {\settrue\c_math_fenced_done
   \ifcsname\??mathleft\normalmeaning\nexttoken\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\math_unknown_left
   \fi}

\def\math_right
  {\settrue\c_math_fenced_done
   \ifcsname\??mathright\normalmeaning\nexttoken\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\math_unknown_right
   \fi}

\def\math_middle
  {\settrue\c_math_fenced_done
   \ifcsname\??mathmiddle\normalmeaning\nexttoken\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\math_unknown_middle
   \fi}

\unexpanded\def\lfence#1%
  {\settrue\c_math_fenced_done
   \let\nexttoken#1%
   \ifcsname\??mathleft\normalmeaning\nexttoken\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\math_unknown_left
   \fi}

\unexpanded\def\rfence#1%
  {\settrue\c_math_fenced_done
   \let\nexttoken#1%
   \ifcsname\??mathright\normalmeaning\nexttoken\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\math_unknown_right
   \fi}

\unexpanded\def\mfence#1%
  {\settrue\c_math_fenced_done
   \let\nexttoken#1%
   \ifcsname\??mathmiddle\normalmeaning\nexttoken\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\math_unknown_middle
   \fi}

\normalexpanded{\installmathfencepair {|\detokenize {|}} \Ldoublebar {|\detokenize {|}} \Rdoublebar}
\normalexpanded{\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 \everymathematics

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

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

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

% Just defined:

\let\Lceil  \Lceiling
\let\Rceil  \Rceiling
\let\Lparent\Lparenthesis
\let\Rparent\Rparenthesis
\let\Lparen \Lparenthesis
\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

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

\unexpanded\def\lbar{\mathortext\mathlbar\textlbar}
\unexpanded\def\rbar{\mathortext\mathrbar\textrbar}

% \setupmathfences[color=darkgreen]

\unexpanded\def\{{\mathortext\lbrace      \letterleftbrace       } % or maybe a chardef
\unexpanded\def\}{\mathortext\rbrace      \letterrightbrace      } % or maybe a chardef
\unexpanded\def\[{\mathortext\lbracket    \letterleftbracket     } % or maybe a chardef
\unexpanded\def\]{\mathortext\rbracket    \letterrightbracket    } % or maybe a chardef
\unexpanded\def\({\mathortext\lparenthesis\letterleftparenthesis } % or maybe a chardef
\unexpanded\def\){\mathortext\rparenthesis\letterrightparenthesis} % or maybe a chardef
\unexpanded\def\|{\mathortext\vert        \letterbar             } % or maybe a chardef
%unexpanded\def\/{\mathortext\solidus     \letterslash           } % or maybe a chardef

\installmathfencepair \{ \Lbrace        \} \Rbrace
\installmathfencepair \[ \Lbracket      \] \Rbracket
\installmathfencepair \( \Lparenthesis  \) \Rparenthesis
\installmathfencepair \&lt; \Langle        \&gt; \Rangle
\installmathfencepair \| \Lbar          \| \Rbar

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

% methods:
%
% 1: none
% 2: lua
% 3: tex

% variants:
%
% 1: step 1
% 2: step 2
% 3: htdp * 1.33^n
% 4: size * 1.33^n

\setnewconstant\bigmathdelimitermethod \plusone
\setnewconstant\bigmathdelimitervariant\plusthree

\unexpanded\def\plainbigdelimiters % traditional method
  {\bigmathdelimitermethod\plustwo}

\plainbigdelimiters % is default for the moment but not so nice

% \setconstant\bigmathdelimitermethod\plusone

\installcorenamespace{mathbig}

\unexpanded\def\choosemathbig#1#2% so we accept \big{||} as well
  {{\naturalhbox\bgroup
      \startimath
        \ifcase\bigmathdelimitermethod
          \math_fenced_step#2\relax
        \or
          \math_fenced_force_size\bigmathdelimitervariant{#1}\relax
          \math_fenced_step#2\relax
        \else
          \math_fenced_step#2{\vpack to\csname\??mathbig\number#1\endcsname\bodyfontsize{}}%
        \fi
        \nulldelimiterspace\zeropoint\relax
        \mathsurround\zeropoint
      \stopimath
    \egroup}}

\def\math_fenced_step#1#2%
  {\setfalse\c_math_fenced_unknown
   \setfalse\c_math_fenced_done
   \left#1\relax
   \ifconditional\c_math_fenced_done
     #2%
     \right.\relax
   \else
     \left.\relax
     #2%
     \setfalse\c_math_fenced_done
     \right#1\relax
     \ifconditional\c_math_fenced_done
     \else
       \right.\relax
     \fi
   \fi}

\unexpanded\def\mathdelimiterstep#1#2%
  {\begingroup
   \math_fenced_force_size\plusone{#1}%
   \math_fenced_step#2\relax
   \endgroup}

\setvalue{\??mathbig1}{0.85}
\setvalue{\??mathbig2}{1.15}
\setvalue{\??mathbig3}{1.45}
\setvalue{\??mathbig4}{1.75}

\definemathcommand [big]  {\choosemathbig\plusone  }
\definemathcommand [Big]  {\choosemathbig\plustwo  }
\definemathcommand [bigg] {\choosemathbig\plusthree}
\definemathcommand [Bigg] {\choosemathbig\plusfour }

\definemathcommand [bigl]  [open]  [one] {\big}
\definemathcommand [bigm]  [rel]   [one] {\big}
\definemathcommand [bigr]  [close] [one] {\big}
\definemathcommand [Bigl]  [open]  [one] {\Big}
\definemathcommand [Bigm]  [rel]   [one] {\Big}
\definemathcommand [Bigr]  [close] [one] {\Big}
\definemathcommand [biggl] [open]  [one] {\bigg}
\definemathcommand [biggm] [rel]   [one] {\bigg}
\definemathcommand [biggr] [close] [one] {\bigg}
\definemathcommand [Biggl] [open]  [one] {\Bigg}
\definemathcommand [Biggm] [rel]   [one] {\Bigg}
\definemathcommand [Biggr] [close] [one] {\Bigg}

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

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

% experimental accents:
%
% \definemathoverextensible [top] [hoed]  ["FE302]
% \definemathoverextensible [top] [slang] ["FE303]

%D This is needed for mathml (used in mrow, so it gets reset):

% old code:

% \let\math_fences_saved_left  \left
% \let\math_fences_saved_middle\middle
% \let\math_fences_saved_right \right
%
% % \def\math_fences_traced#1{\ruledhbox{\ttx#1\low{\the\c_math_fenced_nesting}}}
%
% \unexpanded\def\math_fences_checked_left
%   {%\math_fences_traced L%
%    \math_fences_saved_left}
%
% \unexpanded\def\math_fences_checked_middle
%   {%\math_fences_traced M%
%    \ifcase\c_math_fenced_nesting
%      \expandafter\math_fences_saved_middle
%    \else
%      \expandafter\firstofoneargument
%    \fi}
%
% \unexpanded\def\math_fences_checked_right
%   {%\math_fences_traced R%
%    \ifcase\c_math_fenced_nesting
%      \expandafter\firstofoneargument
%    \else
%      \expandafter\math_fences_saved_right
%    \fi}
%
% \newconditional\c_math_checked_done % only bars
%
% \unexpanded\def\math_fences_checked_left_or_right
%   {%\math_fences_traced B%
%    \ifcase\c_math_fenced_nesting
%      \settrue\c_math_checked_done
%      \expandafter\math_fences_saved_left
%    \else\ifconditional\c_math_checked_done
%      \setfalse\c_math_checked_done
%      \doubleexpandafter\math_fences_saved_right
%    \else
%      \doubleexpandafter\math_fences_saved_middle
%    \fi\fi}
%
% \unexpanded\def\math_fences_checked_start
%   {\c_math_fenced_nesting\zerocount}
%
% \unexpanded\def\math_fences_checked_stop
%   {\ifcase\c_math_fenced_nesting\else
%      \right.\relax % error, todo: nil spacing
%      \expandafter\math_fences_checked_stop
%    \fi}
%
% \unexpanded\def\startcheckedfences
%   {\begingroup
%    \let\left  \math_fences_checked_left
%    \let\middle\math_fences_checked_middle
%    \let\right \math_fences_checked_right
%    \math_fences_checked_start}
%
% \unexpanded\def\stopcheckedfences
%   {\math_fences_checked_stop
%    \endgroup}
%
% \let\leftorright\math_fences_checked_left_or_right % for bars

\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  \leftorright

\unexpanded\def\math_fences_auto_left  #1{\attribute\mathautofenceattribute\plusone  #1\attribute\mathautofenceattribute\attributeunsetvalue}
\unexpanded\def\math_fences_auto_right #1{\attribute\mathautofenceattribute\plustwo  #1\attribute\mathautofenceattribute\attributeunsetvalue}
\unexpanded\def\math_fences_auto_middle#1{\attribute\mathautofenceattribute\plusthree#1\attribute\mathautofenceattribute\attributeunsetvalue}
\unexpanded\def\math_fences_auto_both  #1{\attribute\mathautofenceattribute\plusfour #1\attribute\mathautofenceattribute\attributeunsetvalue}

\let\autofenceopen  \math_fences_auto_left    % for testing
\let\autofenceclose \math_fences_auto_right   % for testing
\let\autofenceleft  \math_fences_auto_left    % for testing
\let\autofenceright \math_fences_auto_right   % for testing
\let\autofencemiddle\math_fences_auto_middle  % for testing
\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

\unexpanded\def\enableautofences
  {\clf_enableautofences
   \glet\clf_enableautofences\relax % onlyonce anyway
   \unexpanded\gdef\enableautofences{\settrue\c_math_fences_auto}%
   \enableautofences}

\unexpanded\def\disableautofences
  {\setfalse\c_math_fences_auto}

\unexpanded\def\math_fences_used_left
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_left
   \else
     \expandafter\math_fences_normal_left
   \fi}
\unexpanded\def\math_fences_used_right
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_right
   \else
     \expandafter\math_fences_normal_right
   \fi}
\unexpanded\def\math_fences_used_middle
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_middle
   \else
     \expandafter\math_fences_normal_middle
   \fi}
\unexpanded\def\math_fences_used_both
  {\ifconditional\c_math_fences_auto
     \expandafter\math_fences_auto_both
   \else
     \expandafter\math_fences_normal_both
   \fi}

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

% wrappers

\unexpanded\def\startcheckedfences
  {\begingroup
   \enableautofences}

\unexpanded\def\stopcheckedfences
  {\endgroup}

% \appendtoks
   % maybe: safeguard against overloading
   %
   % \let\left       \math_fences_used_left
   % \let\right      \math_fences_used_right
   % \let\middle     \math_fences_used_middle
   % \let\leftorright\math_fences_used_both
% \to \everymathematics

\appendtoks
    \ifx\currentmathfence\empty
        \doifelse{\mathfenceparameter\c!state}\v!auto\enableautofences\disableautofences
    \fi
\to \everysetupmathfence

\newconstant\c_math_fences_delimiters_mode \c_math_fences_delimiters_mode"16 % \numexpr"02+"04+"10\relax

%unexpanded\def\enableautofencemode {\mathdelimitersmode\plussix} % the shift (1) is too fragile
\unexpanded\def\enableautofencemode {\mathdelimitersmode\c_math_fences_delimiters_mode}

\unexpanded\def\disableautofencemode{\mathdelimitersmode\zerocount}

\appendtoks
    \ifx\currentmathfence\empty
        \doifelse{\mathfenceparameter\c!method}\v!auto\enableautofencemode\disableautofencemode
    \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.

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

\protect