10

The MWE below

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


The desired output is:

enter image description here

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}
  • 1
    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… – egreg May 12 '16 at 21:30
5

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. ;-)

enter image description here

  • 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 ;. – Peter Grill May 12 '16 at 22:09
  • @PeterGrill The same as for !, I'd say. – egreg May 12 '16 at 22:12

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.