% \iffalse meta-comment
%
%% File: mathcolor.dtx (C) Copyright 2021-2022
%       Frank Mittelbach, LaTeX Team
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
%
%%% From File: mathcolor.dtx
%
%    \begin{macrocode}
\def\mathcolorversion{v1.0c}
\def\mathcolordate{2022/07/25}
%    \end{macrocode}
%<*driver>
\documentclass{l3doc}

%\makeatletter \input{mathcolor.ltx} \makeatother

\usepackage{color}

% Fixing footnotes in  functions and variables: this should be in l3doc!

\newcommand\fixfootnote[2]{\footnotemark
  \AddToHookNext{env/#1/after}{\footnotetext{#2}}}
\AddToHook{env/function/begin}{\def\footnote{\fixfootnote{function}}}
\AddToHook{env/variable/begin}{\def\footnote{\fixfootnote{variable}}}

\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{mathcolor.dtx}
\end{document}
%</driver>
%
% \fi
%
% \title{Providing color in math\thanks{This file has version
%    \mathcolorversion\ dated \mathcolordate, \copyright\ \LaTeX\
%    Project.}}
% \author{Frank Mittelbach}
%
% \maketitle
%
%
% \section{Introduction}
%
%    It is possible to use the \cs{color} command in math formulas but
%    doing that has a number of restrictions and often leads to rather
%    unreadable input. For example, to color the summation sign in red
%    in the following formula
% \[
%     X = \color{red} \sum_{{\color{black} i=1}}^{{\color{black} n}} \color{black} x_i
% \]
%    A total of four color commands and a number of seemingly
%    unnecessary extra braces in the sub and superscript are needed:
%\begin{verbatim}
%  \[ X = \color{red} \sum
%         _{{\color{black} i=1}}  % without {{ the superscript is misplaced
%         ^{{\color{black} n}}    % without {{ the \sum is black
%        \color{black}            % without the x_i is red
%        x_i                  \]
%\end{verbatim}
%    While this is ugly but at least works, other things are simply
%    impossible, e.g.,
% \[  \left\{ \frac{1}{2} \mathcolor{red}{\right\}} \]
%    are not achievable at all because of the fact that \cs{left} and
%    \cs{right} form a group. Thus, a \cs{color} command immediately
%    before the \cs{right} has no effect and \verb=\}= remains black.
%    Putting the color change before the \cs{left} and then resetting
%    the color inside would work if you want to color both braces, but
%    the above combination or the attempt to color only the left brace
%    fails always.
%
%    Using \cs{textcolor} in formulas appears to work on first glance,
%    but it produces spacing problems that are not easy to overcome
%    either, because it generates a single \cs{mathord} and no
%    longer reflects its input, thus
%    \verb/\[ a = b \textcolor{red}{\neq} c \]/
%    produces
%  \[ a = b \textcolor{red}{\neq} c \]
%    This is a case one could mend by wrapping the
%    \cs{textcolor} and its arguments in a \cs{mathrel}, but even when
%    that is possible, the resulting formula source is difficult to
%    maintain and in other situations the solutions are even more
%    complicated or there is no solution at all.
%
%    We therefore offer now a dedicated math coloring command named
%    \cs{mathcolor}.
%
% \begin{function}{\mathcolor}
% \begin{syntax}
%   \cs{mathcolor} \oarg{model} \Arg{color-spec} \Arg{math material}
% \end{syntax}
%    It has the same arguments as \cs{textcolor} but is intended for
%    use in formulas. The command does not generate a group and the
%    \meta{math material} retains its math atom states and it correctly
%    handles sub and superscripts that follow.
% \end{function}
%
%    The command can also be used to color a single opening or closing
%    symbol, e.g., the correct input to our earlier example is
%\begin{verbatim}
%    \[  \left\{ \frac{1}{2} \mathcolor{red}{\right\}} \]
%\end{verbatim}
%    which is how it was produced.
%
%    If you attempt to color large operators that use explicit
%    \cs{limits}, \cs{nolimits}, or \cs{displaylimits}, then these
%    limit controls need to immediately follow the operator. However,
%    \cs{mathcolor} is written in a way that it is possible write
%\begin{verbatim}
%     \[  \mathcolor{red}{\int}\limits_0^1 \textrm{ or }
%         \mathcolor{red}{\int\limits}_0^1                \]
%\end{verbatim}
%    and achieve the same effect:
%     \[  \mathcolor{red}{\int}\limits_0^1 \textrm{ or }
%         \mathcolor{red}{\int\limits}_0^1                \]
%
%
% \MaybeStop{\setlength\IndexMin{200pt}  \PrintIndex  }
%
%
% \section{The Implementation}
%
%    The code is called inside of the \pkg{color} or \pkg{xcolor}
%    packages, so \texttt{@} is already a letter, but the
%    coding here is done in the L3 programming layer, so we need to
%    activate that. But first we check if this file was loaded before,
%    e.g., when both \pkg{color} and \pkg{xcolor} are in the preamble
%    and in that case we stop immediately.
%    \begin{macrocode}
%<*code>
\ifcsname mathcolor\endcsname \endinput \fi
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOn
%<@@=mathcolor>
%    \end{macrocode}
%
%  \begin{macro}{\g_@@_seq}
%    We need to keep our own stack of color commands, so we allocate a
%    sequence for that.
%    \begin{macrocode}
\seq_new:N \g_@@_seq
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\mathcolor}
%    The document-level command which expects a color (if unnamed then
%    the optional argument is the model) and colors the content of the
%    second argument (like \cs{textcolor}, but without spacing
%    problems in math).
%    \begin{macrocode}
\DeclareDocumentCommand \mathcolor { o m m }
  {
%    \end{macrocode}
%    The \cs{mathcolor} is only supported in math mode because in text
%    mode it has problems scanning away a space after it, for example.
%    We therefore raise an error if it executes
%    anywhere else. The \LaTeXe{} error command is a
%    bit strangely named, because in the kernel it is only used for
%    math alphabets, but the message it gives is fine.
% \changes{v1.0b}{2022/01/28}{Restrict command to math mode}
%    \begin{macrocode}
    \mode_if_math:F { \non@alpherr {\mathcolor\space} }
%    \end{macrocode}
%    First real action is to save the current color value on a stack
%    (needed if the command is nested or contains some further color
%    changes with \cs{color} inside).
%    \begin{macrocode}
    \seq_gpush:No \g_@@_seq \current@color
%    \end{macrocode}
%    Then we switch to the new color, but we do not want to reset the
%    color after the group (which is done by \cs{color} using
%    \cs{aftergroup}\cs{reset@color}). The best solution here would be
%    if the color packages  would provide a command doing just the
%    color switching, but for now we simply undo that part by pushing
%    \cs{use_none:n} which gobbles the \cs{reset@color} added by
%    \cs{color} with \cs{aftergroup}.
%    \begin{macrocode}
    \group_insert_after:N \use_none:n
%    \end{macrocode}
%    Switching the color is also slightly suboptimal, because
%    depending on whether or not we have a \meta{model} argument, we
%    have to call \cs{color} with or without the optional argument. But
%    going low-level here is not an option as we need to support
%    different color packages and their internals are not identical.
%    \begin{macrocode}
    \IfValueTF {#1} { \color[#1]{#2} } { \color{#2} }
%    \end{macrocode}
%    Then comes the math material we want to see colored:
%    \begin{macrocode}
    #3
%    \end{macrocode}
%    After that we need to reset the color ourselves (without a group
%    that does it for us), i.e., popping the saved  color from our
%    stack, but there are some twists to that so we do this in a
%    separate command (which in fact needs to be called several times,
%    so inlining the code wouldn't be possible.
%    \begin{macrocode}
    \@@_scan_for_scripts:w
  }
%    \end{macrocode}
%  \end{macro}
%
%
%
%  \begin{macro}{\@@_scan_for_scripts:w}
%    The complication when changing the color back is due to the fact
%    that the \cs{mathcolor} may be followed by \verb=^= or \verb=_=
%    or the hidden superscript \texttt{'} and its argument may end in a
%    \cs{mathop} in which case the sub and superscripts may be
%    attached as \cs{limits} instead of after the material. All cases
%    need separate treatment.
%    And we need to watch out for an upcoming \verb=&= and avoid
%    prematurely triggering the end of an alignment cell.
% \changes{v1.0c}{2022/07/25}{Avoid ending an alignment cell
%    prematurely when hitting an \texttt{\&} during
%                             scanning (gh/901)}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_scan_for_scripts:w
  {
%    \end{macrocode}
%    We need to look at what follows \cs{mathcolor}, and we need to do
%    that ignoring (and dropping) any spaces and \cs{relax} as \TeX{}
%    would do in normal math processing (for example before a subscript
%    token). We do this with expansion so that hidden sub or superscripts
%    in macros are still found as long as the macros are expandable.
%    \begin{macrocode}
    \peek_remove_filler:n
      {
%    \end{macrocode}
%    To avoid problems hitting on \verb=&= we start with a
%    \cs{group_align_safe_begin:}. That has to be ended with
%    \cs{group_align_safe_end:} when the
%    danger (aka scanning) is over, which, due to the branching below, happens at
%    four different points, i.e., when the \cs{mathcolor} is
% \begin{enumerate}
% \item
%    followed by a \enquote{normal} token;
% \item
%    followed by a braced sub/superscript;
% \item
%    followed by an unbraced sub/superscript;
% \item
%    followed by one of the \cs{limits} primitives.
% \end{enumerate}
%    In each case we have to end the align safe group and we mark the
%    points below in the code for easy reference.
%    \begin{macrocode}
        \group_align_safe_begin:
%    \end{macrocode}
%    We first parse for \cs{c_math_subscript_token} or
%    \cs{c_math_superscript_token}.
%    After \cs{peek_remove_filler:n} is done, it sets \cs{l_peek_token}
%    equal to the next non-filler token, so we can avoid unnecessary
%    work and just compare that.  If either of the tokens is found, call
%    \cs{@@_handle_scripts:Nw}:
%    \begin{macrocode}
        \token_case_catcode:NnTF \l_peek_token
          {
            \c_math_subscript_token { }
            \c_math_superscript_token { }
          }
          { \@@_handle_scripts:Nw }
%    \end{macrocode}
%    Otherwise we check if it was any of the limit operation
%    primitives. If that is the case, e.g., if we have a situation
%    such as
%\begin{verbatim}
%    \mathcolor{red}{\int}\limits_1
%\end{verbatim}
%    we have to move it directly after the \cs{int} to ensure there
%    is no color reset between the operator and the \cs{limits} command.
%    \begin{macrocode}
          {
            \token_case_meaning:NnTF \l_peek_token
              {
                \limits   { \limits }
                \nolimits { \nolimits }
                \displaylimits { \displaylimits }
              }
%    \end{macrocode}
%    Once that is done, we have to get rid of the token we peeked at
%    and then restart scanning for sub or superscripts. Given that
%    \cs{@@_scan_for_scripts:w} expands while scanning the simplest
%    solution is to add \cs{use_none:n} in front of the peeked at
%    token.
%
%    Here we end the align safe group and
%    \cs{@@_scan_for_scripts:w} will start a new one.
%    \begin{macrocode}
              {
                \group_align_safe_end:                          % case 4
                \@@_scan_for_scripts:w \use_none:n
              }
%    \end{macrocode}
%    If it was not one of these we look for a \texttt{'} and if found remove it and
%    replace it by its expansion. The reason we have to do this (and
%    not rely on the earlier peeking to expand for us is the fact
%    that \texttt{'} is only ``math active'' and that doesn't expand
%    under \cs{expanded} or \cs{expandafter}.
%    \begin{macrocode}
              {
                \token_if_eq_meaning:NNTF \l_peek_token '
                  {
                    \@@_handle_scripts:Nw ^
                    \c_group_begin_token
                      \exp_after:wN \prim@s \use_none:n
                  }
%    \end{macrocode}
%    If it is anything else we finish off which means we reset the
%    color (because we prevented that before to happen automatically
%    after the next group) and pop the color stack setting \cs{current@color}.
%    \begin{macrocode}
                  {
                    \group_align_safe_end:                      % case 1
                    \reset@color
                    \seq_gpop:NN \g_@@_seq \current@color
                  }
              }
          }
      }
  }
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\@@_handle_scripts:Nw}
%    The tricky part of handling sub and superscripts is that we have
%    to reset color to the one that is on the stack but reset it back
%    to what it was before to allow for cases like
%\begin{verbatim}
%    \[  \mathcolor{red}{a+\sum}_{i=1}^n  \]
%\end{verbatim}
%    Here, \TeX{} constructs a \cs{vbox} stacking subscript, summation
%    sign, and superscript. So technically the superscript comes first
%    and the \cs{sum} that should get colored red is the middle.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_handle_scripts:Nw #1
  {
%    \end{macrocode}
%    The argument is either \verb=^= or \verb=_=, so we execute it and
%    explicitly open two \verb={= groups. We need two because color
%    resets are always done after a group, so the first group is for
%    script material (in case it was just something like \verb=_i=)
%    and the second is needed for the color reset to keep it within
%    the super or subscript. If that reset would happen after it then
%    the color \cs{special} would interfere with \TeX{} math spacing.
%    \begin{macrocode}
    #1 \c_group_begin_token \c_group_begin_token
%    \end{macrocode}
%    Now it is time to change the color back to the one on the stack.
%    \begin{macrocode}
    \seq_get:NN \g_@@_seq \current@color
    \set@color
%    \end{macrocode}
%    \cs{set@color} adds \cs{aftergroup}\cs{reset@color}. We now a add
%    bit more so that the code executed after the current (inner) group
%    looks like this:
%\begin{verbatim}
%      \reset@color } \@@_scan_for_scripts:w
%\end{verbatim}
%    The \cs{@@_scan_for_scripts:w} then retakes control and initiates
%    parsing for another sub or superscript.
%    \begin{macrocode}
    \group_insert_after:N \c_group_end_token
    \group_insert_after:N \@@_scan_for_scripts:w
%    \end{macrocode}
%    Before we give control to \TeX{} to process the sub or
%    superscript some final adjustment is necessary: if the input was
%    \verb=^{...}= then we have one \verb={= too many, because we
%    already supplied the outer one already. In that case we drop
%    it. Otherwise we have an unbraced single token sub or superscript
%    which means we are missing a closing \verb=}= at the end and need
%    to account for that: this is done in false branch by 
%    \cs{use_ii_i:nn}.
%
%    After scanning for a brace all scanning is done, so here are the
%    other two points where we have to end the align safe group (in
%    the true and false case).
%    \begin{macrocode}
    \peek_remove_filler:n
      {
        \token_if_eq_meaning:NNTF \l_peek_token \c_group_begin_token
          {
            \group_align_safe_end:                              % case 2
            \peek_catcode_remove:NT \c_group_begin_token { }
          }
          {
            \exp_after:wN \group_align_safe_end:                % case 3
              \use_ii_i:nn \c_group_end_token
          }
      }
  }
%    \end{macrocode}
%  \end{macro}
%
%    \begin{macrocode}
%<@@=>
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOff
%</code>
%    \end{macrocode}
%
% \Finale
%
%
%%%%%%%%%%%%%%%%
\endinput
%%%%%%%%%%%%%%%%

