8

I am trying to make characters active in math mode, but can't seem to get past the most basic of examples. I would like to define a macro which is passed:

  1. the character to make active and

  2. the macro that should be executed once that macro is encountered.

The MNWE below attempts to make =, + and ! active and color code them. The desired output is that those characters get colored in math mode as. Thus, the input

a=+b $c=+4+d+3!$ e=+f

yields:

enter image description here

where the characters are not altered outside of math mode (the leading a=+b and trailing e=+f).

Notes:

  • There is a separate, but related (as it is in the context of active characters) question in the \MyPlus macro to detect a binary addition + versus a unary positive +. Perhaps that should be a separate question?

Related Questions:

Code (non-working):

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}
\usepackage{xcolor}

\NewDocumentCommand{\MakeActiveChar}{%
    m% char to make active
    m% code to execute for this character
}{%
    \catcode`\#1=13\relax%
    \def#1{#2}%
}%

\let\OldEqual=
\newcommand*{\MyEqual}[1][green]{\mathrel{\textcolor{#1}{\OldEqual}}}%

\let\OldPlus+
\newcommand*{\MyPlus}[1][blue]{%
    %\catcode`\+=12% reset catcode so we can use it (not needed with \OldPlus?)
    %% Perhaps this if-then construct should be a separate question?
    %% if binary addition operator
        \mathbin{\textcolor{#1}{\OldPlus}}%
    %% if unary positive operator
    %%  \mathrel{\textcolor{red}{\OldPlus}}%
}%

\let\OldFactorial!
\newcommand*{\MyFactorial}{\textcolor{brown}{\OldFactorial}}%

\everymath{%
    \MakeActiveChar{=}{\MyEqual}%
    \MakeActiveChar{+}{\MyPlus}%
    \MakeActiveChar{!}{\MyFactorial}%
}%

\begin{document}
The ``math'' outside here is just to test that characters are active \emph{only} in math mode:

a=+b $c=+4+d+3!$ e=+f 
\end{document}
9

You have to be careful with the declarations if you load amsmath; in the body of the definition, use \std{<char>} where you need the old meaning.

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor,etoolbox}

\makeatletter
\newcommand{\DeclareMathActive}[2]{%
  % #1 is the character, #2 is the definition
  \expandafter\edef\csname keep@#1@code\endcsname{\mathchar\the\mathcode`#1 }
  \begingroup\lccode`~=`#1\relax
  \lowercase{\endgroup\def~}{#2}%
  \AtBeginDocument{\mathcode`#1="8000 }%
}

\newcommand{\std}[1]{\csname keep@#1@code\endcsname}
\patchcmd{\newmcodes@}{\mathcode`\-\relax}{\std@minuscode\relax}{}{\ddt}
\AtBeginDocument{\edef\std@minuscode{\the\mathcode`-}}
\makeatother


\DeclareMathActive{+}{\mathbin{\textcolor{blue}{\std{+}}}}
\DeclareMathActive{!}{\mathclose{\textcolor{brown}{\std{!}}}}
\DeclareMathActive{-}{\mathbin{\textcolor{red}{\hat{\std{-}}}}}

\begin{document}

a=+b $c=+4+d+3!-1$ e=+f

\end{document}

Don't do \let\OldPlus=+.

enter image description here

  • Why does the - require special handling? Are there other characters that require special processing? – Peter Grill Mar 19 '16 at 11:01
  • @PeterGrill I made a better fix. – egreg Mar 19 '16 at 11:14
  • You surely know that \expandafter\mathchardef\csname keep@#1@code\endcsname=\mathcode`#1 does similar work like your \edef. – wipet Mar 19 '16 at 13:43
  • @wipet Yes, thanks for reminding, though. – egreg Mar 19 '16 at 13:45
  • 1
    Due to \newmcodes@ having been recently changed in amsopn.sty to better behave with Unicode engines, this (the patch) won't work with XeLaTeX/LuaLaTeX. – user4686 May 13 '16 at 9:08
4

You can define \mathdef declarator and then use it:

\input opmac \localcolor

\def\mathdef#1{\mathcode`#1="8000 \bgroup \lccode`~=`#1\lowercase{\egroup\def~}}

\mathdef +{\mathbin{\Red\mathchar`+}}
\mathdef ={\mathrel{\Green\mathchar`=}}

aha + $a+b+c=d$

\bye

The \input opmac is here only for setting colors \Red, \Green etc. If you are using another macro for colors then use only the second line \def\mathdef... in your macros.

  • 1
    You surely know that \mathord{\mathchar`.} and \mathpunct{\mathchar`,} are different from . and , in math mode. Also \mathbin{\mathchar`-} is quite different from -. Period and comma are taken from the math letters font, whereas the minus is taken from the symbol font. – egreg Mar 19 '16 at 10:49
  • When I attempted to use this I got Illegal parameter number in definition of \mathdef. – Peter Grill Mar 19 '16 at 11:03
3

There are a few problems:

\MakeActiveChar does \def#1{#2} which is not permitted since #1 is a character that is not active. Here's an alternative with The \lowercase trick

\NewDocumentCommand\MakeActiveChar{mm}
  {\begingroup\lccode`\~=`#1\lowercase{\endgroup\def~}{#2}%
   \catcode`#1=12 \mathcode`#1="8000 }

Apart from that, you have a missing = in a \let. The first equal is optional, so \let\a=\b is correct, the equal, however, is necessary when you want to let to = because if not, it would be treated as the optional one, so

\let\originalequal=

should be

\let\originalequal==

And the last part is that by making a character active in math mode, and then doing \newcommand\plus{\mathbin{\originalplus}} you get an endless loop like \def\a{\a}, so you need to use for instance \mathchar`\+ or \mathchar`+ instead.

Complete solution

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}
\usepackage{xcolor}

\NewDocumentCommand\MakeActiveChar{mm}
  {\begingroup\lccode`\~=`#1\lowercase{\endgroup\def~}{#2}%
   \catcode`#1=12 \mathcode`#1="8000 }

\newcommand*\mathcolor[2]{\begingroup\color{#1}#2\endgroup}

\newcommand*\equal[1][green]{\mathrel{\mathcolor{#1}{\mathchar`\=}}}
\newcommand*\plus[1][blue]{\mathbin{\mathcolor{#1}{\mathchar`\+}}}
\newcommand*\factorial{\mathord{\mathcolor{brown}{\mathchar`\!}}}

\everymath{%
  \MakeActiveChar{=}{\equal}%
  \MakeActiveChar{+}{\plus}%
  \MakeActiveChar{!}{\factorial}%
}

\begin{document}
The ``math'' outside here is just to test that characters are active \emph{only} in math mode:

a=+b $c=+4+d+3!$ e=+f 
\end{document}

By the way, I defined \mathcolor because \textcolor works with \bgroup/\egroup which create an ord atom.

  • Can you post a compilable MWE? I get Missing \begin{document} when I replace my definition of \MakeActiveChar with yours. Also, can you explain why you suggest the double equal? If I use the double equal as you suggest, along with your ``\MakeActiveChar, I get TeX capacity exceeded, sorry [grouping levels=255]`. – Peter Grill Mar 19 '16 at 10:26
  • Okey, sorry, I just did it without trying, and the error comes from somewhere else. I'll edit. – Manuel Mar 19 '16 at 10:28
  • Still not a compilable MWE. And again I get LaTeX Error: Missing \begin{document} when I replace your \MakeActiveChar in the MWE I posted in the question. – Peter Grill Mar 19 '16 at 10:52
  • 1
    Sorry about the missing compilable example. The point about \std@minus in egreg answer is interesting, don't miss it. – Manuel Mar 19 '16 at 10:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.