1

I would like \forall to trigger a certain behavior (for the purpose of the example below: change the text color to red), which is cancelled when the next ( is encountered. I can make this work when the ( in question is not within a command, but not when it is. Here is an MWE:

\documentclass{article}
\usepackage{color}

\let\oldforall\forall

\renewcommand{\forall}{%
\oldforall%
\color[rgb]{1,0,0}%
\catcode`(=\active%
}

\let\lparen=(

\catcode`(=\active
\renewcommand{(}{%
\color[rgb]{0,0,0}%
\catcode`(=12\relax%
\lparen}%
\catcode`(=12

\newcommand{\acommand}[1]{#1}

\begin{document}

This works: $\forall x(x^2\geq0)$

This doesn't: \acommand{$\forall x(x^2\geq0)$}

\end{document}

enter image description here

I need a solution that doesn't involve changing the definition of \acommand, as this has to work for any macro that ( may find itself in.

I can understand from “Activate” active characters in argument passed as macro that the issue is that the ( is passed as a passive character to the macro, at which point it is too late to make it active. But I do not understand the solution, so I'm not able to adapt it to my problem.

Casper
  • 246

1 Answers1

3

Catcodes get frozen when a macro fetches its argument.

You can make a variant using the more flexible notion of "math activation", which escapes that restriction.

\documentclass{article}
\usepackage{color}

\usepackage{amsmath}
% added to test compatibility, because it is not generally
% possibly to have a globally (math) active ( with amsmath
% but here activation is done only temporarily

\let\oldforall\forall

\renewcommand{\forall}{%
    \oldforall
    \color[rgb]{1,0,0}%
    \edef\mathcodeofleftparen{\the\mathcode`\(}%
    \mathcode`\(="8000
}

\catcode`(=\active
\def({%
    \color[rgb]{0,0,0}%
    \mathcode`\(=\mathcodeofleftparen\relax
    \string(}
\catcode`(=12

\newcommand{\acommand}[1]{#1}

\begin{document}

This works: $\forall x(x^2\geq0), \forall y(y^3\leq0)$

This too: \acommand{$\forall x(x^2\geq0), \forall y(y^3\leq0)$}

By the way, spacing does not look ideal.

\end{document}

Blockquote

One may also envision redefining \forall as a delimited macro if it is always systematically used with a (.

But either a delimited macro or the approach in the code above does not allow things like \forall x \left(.... Thus I recommend a much simpler approach based on suitable mark-up, for example

\newcommand*{\cforall}[1]{\forall\color[rgb]{1,0,0}#1\color[rgb]{0,0,0}}

to be used as \cforall {x}(stuff), or \cforall x\left(stuff\right) etc...

  • Thank you for your help! With two modifications, your solution worked in my non-MWE real document. 1) The solution does not work if there are multiple occurrences of '\forall' before the first '('. I therefore moved \edef\mathcodeofleftparen{\the\mathcode`(}% outside of the macro. 2) \boldsymbol cannot be used while '(' is active. I found a workaround. – Casper Apr 02 '16 at 09:28
  • @Casper The incompatibility of a math active ( with \boldsymbol (from amsmath) is a known issue related to \resetMathstrut@ inner macro of amsmath. You can check the source code of package mathastext to find a way to redefine \resetMathstrut@ in a way which solves that problem. The code in mathastext.sty however needs some adjustment for general use, as it makes use of math groups defined by mathastext. –  Apr 02 '16 at 16:28