11

I just discovered tikzmark thanks to the blog, and it sounds really promising. I downloaded the files from CTAN and put tikzlibrarytikzmark.code.tex and tikzmarklibrarylistings.code.tex in the same folder as my main .tex file. I'm trying to reproduce the first example from the manual itself, en français.

\documentclass[french]{beamer}

\usepackage{babel}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\begin{document}

\begin{frame}{Test}

   \[
     \tikzmark{a} \frac{x^2}{n!}
   \]

  Test \tikz[remember picture,overlay,baseline=0pt] \draw[->] (0,1em) to (pic cs:a);

\end{frame}

\end{document}

I guess it has to do with the : colon in the tikzmark specific syntax, right? Any ideas on what to do? This compiles just fine if I replace french with english.

Christoph B.
  • 1,901

1 Answers1

10

It's not the colon, it's a buried non-active semi-colon.

TikZ is super-clever with regard to active semi-colons. When it starts a \tikz command (or a \draw or whatever) then it calls a certain macro to gather in the rest of the command. The rest of the command is everything up to the next semi-colon ("up to" with the usual proviso of TeX groupings). However, as there are popular packages like babel make the semi-colon active then the semi-colon delimiting the TikZ command could be either active or non-active (well, it could be a host of things but those are the most likely) and the two are not equivalent. So TikZ checks the state of the semi-colon before calling the macro and calls a different one depending on the state of the semi-colon.

All very well and good.

Enter the tikzmark. This expands to \tikz <something>;. However, it is defined before the document officially begins. This means that the semi-colon has the status of the preambelic semi-colon. babel only changes the state of the semi-colon at the start of the actual document meaning that this semi-colon is not active. But when the \tikzmark is actually used, TikZ checks the current semi-colon status. So it starts looking for an active semi-colon but doesn't find it, causing it to bail out in confusion.

There are probably a few solutions, but I suspect that the best is for \tikzmark to do its own semi-colonic check and use the Right Semi-Colon^TM (TM = tikzmark).

Here's some code that will do that:

\documentclass[french]{beamer}
%\url{https://tex.stackexchange.com/q/110014/86}

\usepackage{babel}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\makeatletter

\begingroup
\catcode`\;=\active

\gdef\tikzmark@active#1#2{%
\tikz[remember picture with id=#2] #1;}

\endgroup
\def\tikzmark@nonactive#1#2{%
\tikz[remember picture with id=#2] #1;}

\renewcommand\tikzmark[2][]{%
\ifnum\catcode`\;=\active
\let\@next=\tikzmark@active
\else
\let\@next=\tikzmark@nonactive
\fi
\@next{#1}{#2}}


\makeatother

\begin{document}

\begin{frame}{Test}

   \[
     \tikzmark{a}
 \frac{x^2}{n!}
   \]

  Test \tikz[remember picture,overlay,baseline=0pt] \draw[->] (0,1em) to (pic cs:a);

\end{frame}

\end{document}

Assuming that no-one tells me that this the Wrong Implementation of Catcode Protection^TM then I'll stick this in the tikzmark code an upload it to CTAN.

Added for clarity This is in essence the same as the problem encountered in tikz declare function and babel french option and Unexpected clash between babel and pgf spy. For each of these then I prefer the solution that involves modifying the original code to cope with active semi-colons - which is what I've done above. Figuring out exactly what needs modifying in such cases is a bit different in each case. Those other questions contain other possibilities that don't require this modification and so are easier for someone to implement themselves in a similar situation. However, I would warn that using beamer can cause a few hiccoughs where catcodes are concerned since catcodes are "frozen" inside frames unless you use the fragile option.

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • No need to scan the arguments twice, just do \renewcommand\tikzmark{% \ifnum\catcode';=\active \expandafter\tikzmark@active \else \expandafter\tikzmark@nonactive \fi } (after putting the ' back to a backtick) – David Carlisle Apr 22 '13 at 11:32
  • @DavidCarlisle Then I'd need to define \tikzmark@active and \tikzmark@nonactive via \newcommand so that they could deal with the optional argument, no? – Andrew Stacey Apr 22 '13 at 11:35
  • @percusse That would be okay, except it could lead to unexpected behaviour if you put something into the \tikzmark arguments that used a semi-colon since it wouldn't behave the same way as outside. – Andrew Stacey Apr 22 '13 at 11:37
  • @AndrewStacey I don't think that's the case if you prefix the code.. – percusse Apr 22 '13 at 11:38
  • @AndrewStacey oh I guess so. – David Carlisle Apr 22 '13 at 11:43
  • Brilliant. Let me know when the CTAN download is updated please. – Christoph B. Apr 22 '13 at 11:51
  • @percusse I'd need to see an example. – Andrew Stacey Apr 22 '13 at 12:20
  • 1
    @ChristophB. I've uploaded it to the TeX-SX Launchpad page (http://bazaar.launchpad.net/~tex-sx/tex-sx/development/files). – Andrew Stacey Apr 22 '13 at 12:21
  • Could you take a look at my modification of \tikzmark in this answer? My suggestion is almost certainly not quite right and certainly not as elegant as you'd come up with, but it does solve the problem raised in the question I'm responding to, which is that the code above breaks in the case that both the babel package and the babel TikZ library are loaded. Since this is a standard recommendation when using TikZ with language configurations which make various characters active, it would be good if tikzmark could handle this case, too. – cfr Oct 23 '16 at 19:51