8

It seems that tikzmark names can't be re-used. In the code below, I try to draw a box outline in the first lstlisting section, and a filled box in the second lstlisting section. In each lstlisting, I place two tikzmarks named "a" and "b". Unfortunately, the result is that the second lstlisting gets both the outline box and the filled box, but the first lstlisting gets neither.

If I rename the tikzmarks in one of the sections (say, "a1" and "b1") things work as expected. Is there a way to "forget" tikzmarks? I'm writing a document that will have a lot of code snippets, and it will be really tedious to keep track of unique tikzmarks for each of them.

Here's the sample code:

\documentclass{article}

\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,calc,shapes,positioning,tikzmark}

\begin{document}
\thispagestyle{empty}

\section{Box}
\begin{lstlisting}[escapechar=!,basicstyle=\ttfamily]
#include <stdio.h>
#include <math.h>

int main () {
  double c=-1;
  double z=0;
  int i;

  printf (``For c = %lf:\n'', c );
  for ( i=0; i<10; i++ ) {
    printf ( !\tikzmark{a}!``z %d = %lf\n''!\tikzmark{b}!, i, z );
    z = pow(z,2) + c;
  }
}
\end{lstlisting}

\begin{tikzpicture}[remember picture,overlay]
\draw[red,rounded corners]
  ([shift={(-3pt,2ex)}]pic cs:a) 
    rectangle 
  ([shift={(3pt,-0.65ex)}]pic cs:b);
\end{tikzpicture}


\section{Filled Box}
\begin{lstlisting}[escapechar=!,basicstyle=\ttfamily]
#include <stdio.h>
#include <math.h>

int main () {
  double c=-1;
  double z=0;
  int i;

  printf (``For c = %lf:\n'', c );
  for ( i=0; i<10; i++ ) {
    printf ( !\tikzmark{a}!"z %d = %lf\n"!\tikzmark{b}!, i, z );
    z = pow(z,2) + c;
  }
}
\end{lstlisting}

\begin{tikzpicture}[remember picture,overlay]
\draw[fill=gray,opacity=0.1]
  ([shift={(-3pt,2ex)}]pic cs:a) 
    rectangle 
  ([shift={(3pt,-0.65ex)}]pic cs:b);
\end{tikzpicture}


\end{document}

Output, showing both outline and filled box applied to 2nd section

  • These names are written to the aux files and can be used anywhere in the code, and in any order. What you CAN do is add \thepage to the name. – John Kormylo Dec 22 '15 at 16:40
  • Unfortunately, I'll often have more than one code snippet per page. It looks like I'll just have to come up with some naming convention and give each tikzmark a unique name. – Bryan Wright Dec 22 '15 at 18:35
  • You certainly can't reuse them on the same page as there will be no way to know which a you mean when stuff is overlaid on the page. So you don't really want the results of reusing names in this case, even if it was allowed. (Presumably, the first would be overwritten by the second or something.) – cfr Jan 11 '16 at 03:07

1 Answers1

11

Here's a solution that uses the fact that tikzmarks can have prefixes and suffices. We create a new counter which we use as the automatically appended suffix. Then each time we use the tikzmarks that we've stored, we increment the counter. By wrapping it all in a few styles, the machinery is quite hidden.

For this to work in its current guise, you have to use the tikzmarks after they've been defined, but the key is when the counter is stepped so it could easily be adapted to a more general case.

\documentclass{article}
%\url{http://tex.stackexchange.com/q/284311/86}

\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,calc,shapes,positioning,tikzmark}

\newcounter{tmkcount}

\tikzset{
  use tikzmark/.style={
    remember picture,
    overlay,
    execute at end picture={
      \stepcounter{tmkcount}
    },
  },
  tikzmark suffix={-\thetmkcount}
}

\begin{document}
\thispagestyle{empty}

\section{Box}
\begin{lstlisting}[escapechar=!,basicstyle=\ttfamily]
#include <stdio.h>
#include <math.h>

int main () {
  double c=-1;
  double z=0;
  int i;

  printf (``For c = %lf:\n'', c );
  for ( i=0; i<10; i++ ) {
    printf ( !\tikzmark{a}!``z %d = %lf\n''!\tikzmark{b}!, i, z );
    z = pow(z,2) + c;
  }
}
\end{lstlisting}

\begin{tikzpicture}[use tikzmark]
\draw[red,rounded corners]
  ([shift={(-3pt,2ex)}]pic cs:a) 
    rectangle 
  ([shift={(3pt,-0.65ex)}]pic cs:b);
\end{tikzpicture}

\section{Filled Box}
\begin{lstlisting}[escapechar=!,basicstyle=\ttfamily]
#include <stdio.h>
#include <math.h>

int main () {
  double c=-1;
  double z=0;
  int i;

  printf (``For c = %lf:\n'', c );
  for ( i=0; i<10; i++ ) {
    printf ( !\tikzmark{a}!"z %d = %lf\n"!\tikzmark{b}!, i, z );
    z = pow(z,2) + c;
  }
}
\end{lstlisting}

\begin{tikzpicture}[use tikzmark]
\draw[fill=gray,opacity=0.1]
  ([shift={(-3pt,2ex)}]pic cs:a) 
    rectangle 
  ([shift={(3pt,-0.65ex)}]pic cs:b);
\end{tikzpicture}


\end{document}

reusing tikzmark names

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • How to use the prefix in a tabular ? https://tex.stackexchange.com/questions/424457/tikzmark-suffix-use-fails?noredirect=1#comment1061952_424457 – Tarass Apr 02 '18 at 14:13