30

While creating a series of graphics (using TikZ) in ConTeXt, I frequently use ConTeXt's buffer to "copy-paste" code. Is there a LaTeX package that implements this feature?

Since most LaTeX users may not know what buffers do, let me explain that. Suppose I want to draw a graph in steps: in the first step, only draw the nodes, in the second step draw the edges, in the third step highlight a part of the graph.

In ConTeXt, I would do this as follows:

\startbuffer[nodes]
% tikz code for drawing nodes
\stopbuffer

\startbuffer[edges]
% tikz code for drawing edges
\stopbuffer

\startbuffer[highlight]
% tikz code for highlight a part
\stopbuffer

\starttext
\startTEXpage \getbuffer[nodes] \stopTEXpage
\startTEXpage \getbuffer[nodes,edges] \stopTEXpage
\startTEXpage \getbuffer[nodes,edges,highlight] \stopTEXpage
\stoptext

This will give me a pdf file with three pages, that build up the graph in steps. How do I do the same in LaTeX?

I can use the preview package to extract TikZ pictures on individual pages, but don't know how to build the graph in steps. One option is to use beamer overlays to create the graph in steps, but creating a presentation for each figure appears to be an overkill. I can just copy paste code, but that is difficult to maintain in the long run. Any suggestions?

Edit

The proposed solution of storing the contents in a macro does not always work. For example

\documentclass{minimal}
\usepackage{tikz}

\def\NODES
  {\matrix
    {
    \node (a) {$a$} ; & \node (b) {$b$} ; \\
    } ;
  }
  
\begin{document}
\begin{tikzpicture}
  \NODES
\end{tikzpicture}
\end{document}

gives

! Package pgfbasematrix Error: Single ampersand used with wrong catcode.

Any other suggestions?

2
  • How does context work around the problem you note in the update? I assume it must use \scantokens. Nov 20, 2010 at 6:19
  • 2
    @Will: the content is treated as a verbatim block that is processed one line at a time, ending with the literal string "\stopbuffer" at the start of a line. Nov 20, 2010 at 8:17

6 Answers 6

15

Not really a proper answer, but perhaps it is useful as hint:

Based on what buffers do, the filecontents environment combined with \input (for \getbuffer) and \verbatiminput (for \typebuffer) comes closest, I think.

1
  • Thanks. filecontents does work the same way as buffers in MkII. I can use \begin{filecontents}{\jobname-nodes.tmp} ... \end{filecontents} and then just \input{\jobname-nodes.tmp}. I think that this the most failsafe solution because no catcode trickery is required.
    – Aditya
    Nov 20, 2010 at 15:08
13

The following code shows three possible solutions to the updated question.

\documentclass{minimal}
\usepackage{tikz}

\def\NODESa
  {\matrix
    {
    \node (a) {$a$} ; & \node (b) {$b$} ; \\
    } ;
  }

\def\NODESb
  {\matrix[ampersand replacement=\&]
    {
    \node (a) {$a$} ; \& \node (b) {$b$} ; \\
    } ;
  }

\begingroup
\catcode`\&=\active
\def\x#1{#1}%
\x{%
\endgroup
\def\NODESc
  {\matrix
    {
    \node (a) {$a$} ; & \node (b) {$b$} ; \\
    } ;
  }
}

\begin{document}
\begin{tikzpicture}
  \scantokens\expandafter{\NODESa}
\end{tikzpicture}
\begin{tikzpicture}
  \NODESb
\end{tikzpicture}
\begin{tikzpicture}
  \NODESc
\end{tikzpicture}
\end{document}
4
  • What does \scantokens do? The other two I understand (and had been thinking about), but might not be clear in general. Nov 20, 2010 at 2:16
  • 5
    @antal it retokenises its argument with the current catcode settings. Equivalent to writing the argument verbatim to a file and \input-ing it in again. Using \scantokens here would be my favored approach, I think. Nov 20, 2010 at 6:21
  • 2
    @Antal: One should add that \scantokens is an e-TeX primitive (that I'd never heard of until now). Nov 20, 2010 at 9:12
  • Thanks. I did not know that tikz sets & to be active. All three solutions work perfectly.
    – Aditya
    Nov 20, 2010 at 15:05
10

Based on Joel's comment above, I'd just write

\def\buffernodes{
  % tikz code for drawing nodes
}
\def\bufferedges{
  % tikz code for drawing edges
}
\def\bufferhighlight{
  % tikz code for highlight a part
}

\buffernodes
\newpage
\buffernodes\bufferedges
\newpage
\buffernodes\bufferedges\bufferhighlight

You could write a wrapper to implement a more ConTeXt-like buffer interface, but for this simple example I think it's fine as-is.

3
  • Yeah, probably should have submitted as an answer, but was too busy to mock up a demo. Well done. Nov 14, 2010 at 4:23
  • Thanks. For this case, this seems to be the easiest way to go. (ConTeXt buffers do other things also, but I do not need those features in this case).
    – Aditya
    Nov 14, 2010 at 4:36
  • 1
    This solution does not always work. See the updated question.
    – Aditya
    Nov 20, 2010 at 0:43
5

I leave this answer here only because this post served as general inspiration since I joined the forum, unfortunately I am not a user of ConTeXt :( but, with the package scontents you can imitate the concept of buffers.

\documentclass{article}
\usepackage[store-cmd=tikz]{scontents}
\usepackage{tikz}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\Scontents*{\matrix{ \node (a) {$a$} ; & \node (b) {$b$} ; \\ } ;}
\Scontents*{\matrix[ampersand replacement=\&]
{ \node (a) {$a$} ; \& \node (b) {$b$} ; \\ } ;}
\Scontents*{\matrix{\node (a) {$a$} ; & \node (b) {$b$} ; \\ } ; }
\begin{document}
\section{tikzpicture}
\begin{tikzpicture}
\getstored[1]{tikz}
\end{tikzpicture}

\begin{tikzpicture}
\getstored[2]{tikz}
\end{tikzpicture}

\begin{tikzpicture}
\getstored[3]{tikz}
\end{tikzpicture}

\begin{scontents}[store-env=buffer]
Hello World!

This is a \verb*|fake poor man's buffer| :).
\end{scontents}

\section{source tikz}
\typestored[1]{tikz}
\typestored[2]{tikz}
\typestored[3]{tikz}

\section{fake buffer}
\subsection{real content}
\getstored[1]{buffer}
\subsection{verbatim style}
\typestored[1]{buffer}
\subsection{meaning}
\meaningsc[1]{buffer}

\section{tikz again}
\foreachsc[before={\begin{tikzpicture}},after={\end{tikzpicture}},sep={\\[10pt]}]{tikz}
\end{document}

output Saludos

3
  • scontents works in ConTeXt, too. In fact, it is more robust in some aspects as I could experiment.
    – user193767
    Jun 30, 2020 at 16:52
  • 1
    Great that it's helpful, this post was the original inspiration :). Jul 1, 2020 at 21:47
  • I've just seen you're the main developer of scontents. Chapeau
    – user193767
    Jul 1, 2020 at 21:49
4

You can emulate a poor man's buffer using toks registers and e-TeX's \scantokens. As you can see \typebuffer does not work as intended but \getbuffer seems to work fine.

\def\setverb{\def\do##1{\catcode`##1=12}\dospecials}

\newtoks\buffer
\def\startbuffer{\begingroup\setverb\tt\dobuffer}
{\catcode`\|=0 |catcode`|\=12
|long|gdef|dobuffer#1\stopbuffer{%
  |expandafter|global|buffer={#1}%
  |endgroup}}
\def\typebuffer{{\tt\the\buffer}}
\def\getbuffer{\expandafter\scantokens\expandafter{\the\buffer}}

\startbuffer
\def\x{abc}
\x

Hello World!

This is a poor man's buffer.
\stopbuffer

\typebuffer

\bigbreak

\getbuffer

\bye

enter image description here

0

You could use the Beamer package which works well with Tikz.

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\begin{frame}
\begin{tikzpicture}
\onslide<+->{
% tikz code for drawing nodes
}
\onslide<+->{
% tikz code for drawing edges
}
\onslide<+->{
% tikz code for highlight a part
}
\end{tikzpicture}
\end{frame}
\end{document}

I am actually looking for the ConTeXt equivalent of this. Thanks for your tip in your question. But do you know if and how ConTeXt could do it without generating multiple pages for these "overlays" (in the language of Beamer)? Beamer has a really good manual called the Beamer Guide.

1
  • This is a neat use of Beamer's overlays, although I think not quite as general as ConTeXt's buffer concepts i.e. this is restricted to same frame effects.
    – Dai Bowen
    Oct 22, 2016 at 10:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .