%% abraces.sty
%% Copyright 2024 Werner Grundlingh
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Werner Grundlingh.
%
% This work consists of the file abraces.sty.

\ProvidesPackage{abraces}% http://ctan.org/pkg/abraces
  [2024/08/02 v2.2 Arbitrary and asymmetric braces]

% xparse definitions now form part of the LaTeX core. However, keeping this in for those using older versions.
\RequirePackage{xparse}
% Since abraces defines \bracecolor, add xcolor as dependency
\RequirePackage{xcolor}

\newif\if@overload
\DeclareOption{overload}{\@overloadtrue}
\ProcessOptions
\newsavebox{\bracebox}% stores content contained under/over brace

\newcommand{\newbracespec}[2]{% Add a new brace specification based on existing ones
  \@defbracecharcode{#1}{\@genbrace#2\@nnil\@genbrace}
}
% Brace components
\newcommand{\bracescript}[1]{{% Add a script above/below an over-/underbrace
  \let\@@bfil\@@bunfil% Make line leaders into void/empty leaders
  \let\@use@rl@se\phantom% Phantomize some brace components
  \makebox[\wd\bracebox]{$\genbrace{#1}$}% Place the text in a box of width \bracebox
}}
\def\@@bunfil{\leaders\hbox{\ }\hfill}% Empty filler
\newcommand{\bracefil}[1]{%
  \csname brace@char@#1'\endcsname%
}
\def\@@bfil{\leaders \vrule \@height \ht\z@ \@depth \z@ \hfill}% default brace filler
%\def\bfil{\@@bfil}%
%\def\@bLfil{\@@bfil}% left leader filler
%\def\@bRfil{\@@bfil}% right leader filler
\def\aupbracefill#1{$\m@th\setbox\z@\hbox{$\braceld$}\genbrace{#1}$}
\def\adownbracefill#1{$\m@th\setbox\z@\hbox{$\braceld$}\genbrace{#1}$}

\DeclareDocumentCommand{\downbracketend}{ O{.7\fontdimen5\textfont2} }{%
  \@use@rl@se
    {\sbox\z@{$\braceld$}%
    \dimen@\ht\z@ \advance\dimen@#1\relax
    \vrule \@width\ht\z@ \@height\ht\z@ \@depth\dimexpr\dimen@-\ht\z@}%
    \@genbrace}

\DeclareDocumentCommand{\upbracketend}{ O{.7\fontdimen5\textfont2} }{%
  \@use@rl@se
    {\sbox\z@{$\bracelu$}%
    \dimen@\ht\z@ \advance\dimen@#1\relax
    \vrule \@width\ht\z@ \@height\dimen@ \@depth\z@}%
    \@genbrace}

% Repetition structure. Reference:
%   Repeat command n times?
%   http://tex.stackexchange.com/q/16189/5764
\ExplSyntaxOn
\cs_new_eq:NN \Repeat@br@ces \prg_replicate:nn
%FMi
\cs_new_eq:NN \TrimArgSpaces \tl_trim_spaces:n  % only needed when ^{...} should be text
%FMi
\ExplSyntaxOff

% Taken from mathtools package (http://ctan.org/pkg/mathtools)
\DeclareDocumentCommand{\aunderbrace}{ O{l1D1r} m o e{^_}}{%
  \begin{lrbox}{\bracebox}$\displaystyle{#2}$\end{lrbox}%
  \mathop{\vtop{\m@th\ialign{##\crcr
    $\hfil\displaystyle{#2}\hfil$\crcr
    \noalign{\kern.7\fontdimen5\textfont2\nointerlineskip}%
    \aupbracefill{#1}\crcr\noalign{\kern.5\fontdimen5\textfont2}}}}\limits
    % ...there was a ^:
    \IfValueT{#4}{%
    ^{%
%FMi
      \gdef\@abrace@text@arg{#4}%  % save argument then split of portions later
%FMi
      \@defbracecharcode{A}{%
        \@use@rl@se\braceru
        \makebox[0pt][c]{\scriptsize
%FMi % split off next part
            \expandafter\@abrace@next@text\@abrace@text@arg&\@abrace@next@text}%
%FMi
        \@use@rl@se\bracelu\@genbrace
      }%
      % We interpret U as A
      \let\brace@char@U\brace@char@A
%FMi
      \let\@abrace@stuff\phantom       % render @{...} harmless
%FMi
      % Use the normal spec by default
      \IfValueTF{#3}
        {\bracescript{#3}}% Use newly-specified spec
        {\bracescript{#1}}% Use default spec
%FMi
      \@abrace@is@arg@fully@used{^}{U}%
%FMi
    }%
  }%
  % ...there was a _:
  \IfValueT{#5}{%
  _{%
%FMi
    \gdef\@abrace@text@arg{#5}%
%FMi
    \@defbracecharcode{A}{%
        \@use@rl@se\bracerd
        \makebox[0pt][c]{%
          \scriptsize           % not needed if processed in math
%FMi
          \expandafter\@abrace@next@text\@abrace@text@arg&\@abrace@next@text}%
%FMi
        \@use@rl@se\braceld\@genbrace
    }%
    % We interpret D as A
    \let\brace@char@D\brace@char@A
%FMi
      \let\@abrace@stuff\phantom       % render @{...} harmless
%FMi
    % Use the normal spec by default
    \IfValueTF{#3}
      {\bracescript{#3}}% Use the newly-specified spec
      {\bracescript{#1}}% Use the default spec
%FMi
    \@abrace@is@arg@fully@used{_}{D}%
%FMi
    }%
  }%
%FMi
% If there is a second optional argument (#3) but there is neither
% a ^{..} nor a _{..} then interpret the bracket group was not an optional argument
% but actually belongs to the current formula, so return it.
% Order of the test is #3 #5 #4 because an overbrace is more likely to have ^{..}.
% For underbrace it is #3 #4 #5.
  \IfValueT{#3}{\IfValueF{#5}{\IfValueF{#4}{[#3]}}}%
%FMi
}

%\RequirePackage{unravel}

%FMi
\def\@abrace@next@text#1&#2\@abrace@next@text{%
  \gdef\@abrace@text@arg{#2}%
  %  \TrimArgSpaces{#1}%                 % text solution
  $\scriptstyle #1$%                     % use math mode instead? I think so
}
%FMi



%FMi
% check if current value of \@abrace@text@arg contains parts that haven't been used.
%
% Possible cases: (a) empty (b) one or more & symbols (c) some & symbol(s) and other stuff
%
% (c) is the case we need to generate an error for.


\def\@abrace@is@arg@fully@used#1#2{%
  \edef\abrace@tempa{\detokenize{#1}}%   _ or ^
  \def\abrace@tempb{#2}%             %   D or U
  \let\abrace@next\@abrace@is@arg@fully@used@
  \expandafter\@abrace@is@arg@fully@used@ \@abrace@text@arg \@nil &%
}

% As we know that here is at least \verb=\@nil &= in the stream ahead
% we can grep one argument delimited by \verb=&= and then check if it
% is empty (case (a) or (b)), if it is \verb=\@nil= (we are done) or
% if it is anything else (case (c)).


\def\@abrace@is@arg@fully@used@ #1&{%
  \def\@abrace@text@arg{#1}%
  \ifx\@abrace@text@arg\@empty                  % ok case
  \else
    \ifx\@abrace@text@arg\@nnil                 % we are done
      \let\abrace@next\relax
    \else
      \PackageError{abraces}{Unused part in \abrace@tempa{...}:\MessageBreak
                             '\detokenize{#1}' dropped}%
                            {There have been more \string& symbols than
                             \abrace@tempb\space or A elements in the pattern.
                             Check your source!}%
    \fi
  \fi
  \abrace@next
}    
%FMi

  

\DeclareDocumentCommand{\aoverbrace}{ O{L1U1R} m o e{^_}}{%
%
%  \typeout{Arguments: \detokenize{1=#1|2=#2|3=#3|4=#4|5=#5|}}%
%    
  \begin{lrbox}{\bracebox}$\displaystyle{#2}$\end{lrbox}%
  \mathop{\vbox{\m@th\ialign{##\crcr
    \noalign{\kern.5\fontdimen5\textfont2}%
    \adownbracefill{#1}\crcr
    \noalign{\kern.7\fontdimen5\textfont2\nointerlineskip}%
    $\hfil\displaystyle{#2}\hfil$\crcr}}}\limits
    % ...there was a ^:
    \IfValueT{#4}{%
    ^{%
      % Define a text point instead of a tip
%FMi
      \gdef\@abrace@text@arg{#4}%  % save argument then split of portions later
%FMi
      \@defbracecharcode{A}{%
        \@use@rl@se\braceru
        \makebox[0pt][c]{\scriptsize
%FMi % split off next part
            \expandafter\@abrace@next@text\@abrace@text@arg&\@abrace@next@text}%
%FMi
        \@use@rl@se\bracelu\@genbrace
      }%
      % We interpret U as A
      \let\brace@char@U\brace@char@A
      % Use the normal spec by default
%FMi
      \let\@abrace@stuff\phantom       % render @{...} harmless
%FMi
      \IfValueTF{#3}
        {\bracescript{#3}}% Use newly-specified spec
        {\bracescript{#1}}% Use default spec
%FMi
      \@abrace@is@arg@fully@used{^}{U}%
%FMi
    }%
  }%
  % ...there was a _:
  \IfValueT{#5}{%
    _{%
    % Define a text point instead of a tip
%FMi
      \gdef\@abrace@text@arg{#5}%
%FMi
    \@defbracecharcode{A}{%
        \@use@rl@se\bracerd
        \makebox[0pt][c]{%
          \scriptsize           % not needed if processed in math
          %FMi
          \expandafter\@abrace@next@text\@abrace@text@arg&\@abrace@next@text
        }%
%FMi
        \@use@rl@se\braceld\@genbrace
    }%
    % We interpret D as A
    \let\brace@char@D\brace@char@A
%FMi
      \let\@abrace@stuff\phantom       % render @{...} harmless
%FMi
    % Use the normal spec by default
    \IfValueTF{#3}
              {\bracescript{#3}}% Use the newly-specified spec
              {\bracescript{#1}}% Use the default spec
%FMi
    \@abrace@is@arg@fully@used{_}{D}%
%FMi
    }%
  }%
%FMi
  \IfValueT{#3}{\IfValueF{#4}{\IfValueF{#5}{[#3]}}}%
%FMi
}

% Parsing structure. Reference:
%   Parsing a macro argument character-by-character for conditional execution
%   http://tex.stackexchange.com/q/33197/5764

\let\@use@rl@se\relax
\def\@defbracecharcode#1{% Macro to define brace character "codes"
  \@namedef{brace@char@#1}%
}
\@defbracecharcode{L}{\@use@rl@se\braceld\@genbrace}% Left down
\@defbracecharcode{R}{\@use@rl@se\bracerd\@genbrace}% Right down
\@defbracecharcode{l}{\@use@rl@se\bracelu\@genbrace}% Left up
\@defbracecharcode{r}{\@use@rl@se\braceru\@genbrace}% Right up
\@defbracecharcode{U}{\@use@rl@se\braceru\@use@rl@se\bracelu\@genbrace}% Tip up
\@defbracecharcode{D}{\@use@rl@se\bracerd\@use@rl@se\braceld\@genbrace}% Tip down
\@defbracecharcode{0}{\@@bunfil\@genbrace}% Do nothing
\@defbracecharcode{1}{\@@bfil\@genbrace}% 1 filler
\@defbracecharcode{2}{\@@bfil\@@bfil\@genbrace}% 2 fillers
\@defbracecharcode{3}{\@@bfil\@@bfil\@@bfil\@genbrace}% 3 fillers
\@defbracecharcode{4}{\@@bfil\@@bfil\@@bfil\@@bfil\@genbrace}% 4 fillers
\@defbracecharcode{5}{\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@genbrace}% 5 fillers
\@defbracecharcode{6}{\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@genbrace}% 6 fillers
\@defbracecharcode{7}{\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@genbrace}% 7 fillers
\@defbracecharcode{8}{\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@genbrace}% 8 fillers
\@defbracecharcode{9}{\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@@bfil\@genbrace}% 9 fillers
\@defbracecharcode{@}{\@firstofone@go}% Insert arbitrary stuff
\@defbracecharcode{!}{\@firstofone@len}% Insert a leader of specific length
\@defbracecharcode{*}{\@repeat@num@times}% Repeat stuff a number of times
\@defbracecharcode{,}{\downbracketend}% Downward bracket end
\@defbracecharcode{'}{\upbracketend}% Upward bracket end


%FMi
%like U or D (same width) but a straight line marking a possible anchor point for annotation material
% can be used in patterns, e.g., $\aunderbrace[3A1]{a+b+c+d}_{x}$  makes a an underline rule with
% the "x" being placed off center

\@defbracecharcode{A}{%
  \setbox\z@\hbox{$\m@th\braceru\bracelu$}%
  \hb@xt@\wd\z@{\@@bfil}%
  \@genbrace}%  
                   
%FMi


\newcommand{\bracecolor}[1]{\xdef\bracecolor@{\noexpand\color{#1}}\aftergroup\bracecolor@}
%FMi
\let\bracecolor\color  % no longer needed
%\newcommand{\@firstofone@go}[1]{\mathord{#1}\@genbrace}%
\let\@abrace@stuff\@firstofone
\newcommand{\@firstofone@go}[1]{\mathord{}\@abrace@stuff{#1}\mathord{}\@genbrace}%
%FMi
%\newcommand{\@firstofone@go}[1]{#1\@genbrace}%
\newcommand{\@firstofone@len}[1]{\hb@xt@#1{\@@bfil}\@genbrace}%
\newcommand{\@repeat@num@times}[2]{\Repeat@br@ces{#1}{\@genbrace#2\@nnil}\@genbrace}%

\newcommand{\@genbrace}[1]{%
  \ifx\@nnil#1\relax\else
%FMi
    \expandafter\ifx\csname brace@char@#1\endcsname\relax
    \PackageError{abraces}{Brace pattern '#1' unknown}%
      {I'll use '0' instead.}%
      \csname brace@char@0\expandafter\expandafter\expandafter\endcsname
    \else
      \csname brace@char@#1\expandafter\expandafter\expandafter\endcsname
    \fi
%FMi
  \fi
}
\newcommand{\genbrace}[1]{%
  \@genbrace#1\@nnil%
}

% If package was loaded with \usepackage[overload]{abraces}
\if@overload
  \let\overbrace\aoverbrace
  \let\underbrace\aunderbrace
\fi
\endinput