Active ! Character Hangs within TikZ

The MWE below

However, when the ! is active within the \hcancel compilation seems to hang?

The desired output is:

but if I uncomment the code intend to produce the the last canceled term the compilation seems to hang.

Code:

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor,etoolbox}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
%% https://tex.stackexchange.com/questions/299798/make-characters-active-via-macro-in-math-mode
\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{!}{\mathclose{\textcolor{blue}{\std{!}}}}

%% https://tex.stackexchange.com/questions/20643/diagonal-strikeout-starting-too-low-and-ending-too-high
\newcommand{\hcancel}[5]{%
\tikz[baseline=(tocancel.base)]{
\node[inner sep=0pt,outer sep=0pt] (tocancel) {#1};
\draw[red] ($(tocancel.south west)+(#2,#3)$) -- ($(tocancel.north east)+(#4,#5)$);
}%
}%

\begin{document}

Active ! works: $3!$

Cancel with non-active ! works:
\hcancel{$3\std{!}$}{-3pt}{0pt}{3pt}{0pt}

\medskip
Combine cancel with active ! hangs:
%\hcancel{$3!$}{-3pt}{0pt}{3pt}{0pt}% <-- This hangs!!

\end{document}

• As part of its workarounds connected to babel, TikZ changes the meaning of the active ! to \tikz@nonactiveexlmark, which expands to a ! with category code 12, which then expands to \tikz@nonactiveexlmark, which… May 12, 2016 at 21:30

You're being very unlucky.

The French module for babel makes ! into an active character, in order to implement the French conventions about punctuation. Therefore, since the beginning, TikZ takes precautions against this, because it uses ! in its syntax. Therefore it assigns a new meaning to the active ! in case French is being used.

It essentially does

\begingroup\lccode~=! \lowercase{\endgroup\def~}{\tikz@nonactiveexlmark}
\edef\tikz@nonactiveexlmark{\string!}


Similarly for ;, : and |. So in a tikzpicture environment the assigned meaning \mathclose{\textcolor{blue}{\std{!}}} is lost. Worse, when ! is math active, TeX enters an infinite loop:

• ! in math mode is treated as if it were active, so it is replaced by its meaning \tikz@nonactiveexlmark

• \tikz@nonactiveexlmark is replaced by its meaning, a ! with category code 12

• ! in math mode is treated as if it were active, so it is replaced by its meaning \tikz@nonactiveexlmark

Since you're not using French, you can redefine \tikz@nonactiveexlmark do to the same as the math active !.

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor,etoolbox}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
%% http://tex.stackexchange.com/questions/299798/make-characters-active-via-macro-in-math-mode
\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 }%
}

\def\tikz@nonactiveexlmark{\mathclose{\textcolor{blue}{\std{!}}}}

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

\DeclareMathActive{!}{\mathclose{\textcolor{blue}{\std{!}}}}

%% http://tex.stackexchange.com/questions/20643/diagonal-strikeout-starting-too-low-and-ending-too-high
\newcommand{\hcancel}[5]{%
\tikz[baseline=(tocancel.base)]{
\node[inner sep=0pt,outer sep=0pt] (tocancel) {#1};
\draw[red] ($(tocancel.south west)+(#2,#3)$) -- ($(tocancel.north east)+(#4,#5)$);
}%
}%

\begin{document}

Active ! works: $3!$

Cancel with non-active ! works:
\hcancel{$3\std{!}$}{-3pt}{0pt}{3pt}{0pt}

\medskip
Combine cancel with active ! hangs:
\hcancel{$3!$}{-3pt}{0pt}{3pt}{0pt}% <-- This hangs!!

\end{document}


The text now tells a lie. ;-)

• Wow, those darn French go and make things complicated! :-) I would have thought since these are active only in math mode, that I would not run into such problems - oh, well. So, what would I need to do for the other characters, especially the : and|. Don't think I'll have an issue with the ;. May 12, 2016 at 22:09
• @PeterGrill The same as for !, I'd say. May 12, 2016 at 22:12