2

I have seen answers to this question floating around but none of them appeared to solve the problem.

I want to be able to throw a code block into an already defined tikzpicture. So I attempted to make a command that replaces \node{}; and ran into a known problem with verbatim-like environments inside commands.

I have a complete example here. It does not build with pdflatex. Notice blue \node works, but \rednode fails.

\documentclass{beamer}
\usepackage{tikz}
\usepackage{listings}

\newcommand{\rednode}[1]{
   \node[draw=red]{#1};
}

\begin{document}

\begin{frame}[fragile]

\begin{tikzpicture}

   \node[draw=blue]{
\begin{lstlisting}
int main()
{
    printf("Hello World\n");
} 
\end{lstlisting}
   };

   \rednode{
\begin{lstlisting}
int main()
{
    printf("Hello World\n");
} 
\end{lstlisting}
   }

\end{tikzpicture}

\end{frame}

\end{document}

Solutions explored involve the cprotect package, tabular environments, and minipage environments.

Torbjørn T.
  • 206,688
William
  • 65

2 Answers2

3

Box the listing before using it in the argument for \node:

\documentclass{beamer}
\usepackage{tikz}
\usepackage{listings}

\newcommand{\rednode}[1]{
   \node[draw=red]{#1};
}

\newsavebox\mybox

\begin{document}

\begin{lrbox}{\mybox}
\begin{lstlisting}
int main()
{
    printf("Hello World\n");
} 
\end{lstlisting}
\end{lrbox}

\begin{frame}[fragile]
\begin{tikzpicture}
\node[draw=blue]{};
\rednode{\usebox\mybox}: 
\end{tikzpicture}
\end{frame}

\end{document}

The result:

enter image description here

With this approach you don't need the fragile option for frame; I left it just in case you want to add some other non previously boxed verbatim material.

Gonzalo Medina
  • 505,128
0

Well, cprotect does work in this simple case. OP probably didn't use it correctly.

\documentclass{beamer}
\usepackage{tikz}
\usepackage{listings}
\usepackage{cprotect}

\newcommand{\rednode}[1]{ \node[draw=red]{#1}; }

\begin{document}

\begin{frame}[fragile]

\begin{tikzpicture}

\node[draw=blue]{ \begin{lstlisting} int main() { printf("Hello World\n"); } \end{lstlisting} };

\cprotect\rednode{ \begin{lstlisting} int main() { printf("Hello World\n"); } \end{lstlisting} }

\end{tikzpicture}

\end{frame}

\end{document}

Or use \cMakeRobust, as mentioned in the documentation of cprotect package:

\documentclass{beamer}
\usepackage{tikz}
\usepackage{listings}
\usepackage{cprotect}

\newcommand{\rednode}[1]{ \node[draw=red]{#1}; } \cMakeRobust{\rednode}

\begin{document}

\begin{frame}[fragile]

\begin{tikzpicture}

\node[draw=blue]{ \begin{lstlisting} int main() { printf("Hello World\n"); } \end{lstlisting} };

\rednode{ \begin{lstlisting} int main() { printf("Hello World\n"); } \end{lstlisting} }

\end{tikzpicture}

\end{frame}

\end{document}

user202729
  • 7,143