TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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}
share|improve this question
    
Perhaps that question about binary should indeed be a different question :) – Manuel Mar 19 at 10:13
    
For the colour changing, can I point out this question: tex.stackexchange.com/q/335/86 Based on this, I had a working method that I used happily for many years. – Loop Space Mar 19 at 12:44
    
@LoopSpace: Thanks. Will have a look. – Peter Grill Mar 19 at 13:26
    
@PeterGrill If you want a working implementation, just ask. – Loop Space Mar 19 at 13:45
    
Follow-up Question: Active ! Character Hangs within TikZ – Peter Grill May 12 at 21:20
up vote 6 down vote accepted

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

share|improve this answer
    
Why does the - require special handling? Are there other characters that require special processing? – Peter Grill Mar 19 at 11:01
    
@PeterGrill I made a better fix. – egreg Mar 19 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 at 13:43
    
@wipet Yes, thanks for reminding, though. – egreg Mar 19 at 13:45
    
There is a bug in \DeclareMathActive: it should use two space tokens in the replacement text of \csname keep@#1@code\endcsname. eg try $\std{t}1$ with \DeclareMathActive{t}{U}. (or $\std{+}1$ in the context of your answer; I came here from another question which was linking to it) (you could put a \relax at the end of \std definition) – jfbu May 13 at 9:00

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.

share|improve this answer
    
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 at 10:26
    
Okey, sorry, I just did it without trying, and the error comes from somewhere else. I'll edit. – Manuel Mar 19 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 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 at 10:54

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.

share|improve this answer
    
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 at 10:49
    
When I attempted to use this I got Illegal parameter number in definition of \mathdef. – Peter Grill Mar 19 at 11:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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