22

I am writing a \newcommand which outputs an image. I'd like to have the source that was used to make that image in the appendix (\lstinputlisting). How can I collect sources of all the used images all over my document and then output them when making the appendix part?

I have seen this question, but I dreamt of something like \savebox but with the option to add my content to the existing one.

Any help? :)

Edit

I ended up using code based on the collect package recommended by Gonzo Medina, see the MWE:

\documentclass{article} 
\usepackage[demo]{graphicx}

\usepackage{collect}
\definecollection{myexamples}
% call like this: \example{01-start}{01-start-output-image}{My caption}
\newcommand{\example}[3]{
    \begin{figure}[htbp]
      \begin{center}
        \label{example:#1}
        \includegraphics[height=5cm]{images/#2} 
        \caption{#3}
      \end{center}
    \end{figure}
    % collecting the code for appendix:
    \begin{collect}{myexamples}{}{}
      \subsection{#1}
      Include your code for example #1 here, e.g. using the listings package.

      The example has been printed on page \pageref{example:#1}.
    \end{collect}
}

\begin{document}

\section{First Section}
\example{01-merge}{01-merge-image}{Caption1}

\newpage
\section{Second Section}
\example{02-merge}{02-merge-image}{Caption2}
\example{03-merge}{03-merge-image}{Caption3}

\newpage
\appendix
\section{Code}

\includecollection{myexamples}
\end{document}

Thank you very much for your answers!

Johannes
  • 583

2 Answers2

18

The collect package could be useful here. A little example: a new myplots collection is defined; the newly defined environment collplot typesets its content in the document and also stores it in the collection using a lstlisting environment; when \includecollection{myplots} is invoked, the code used to produce the plots is typeset using a frame with colored background:

\documentclass{article}
\usepackage{collect}
\usepackage{listings}
\usepackage{pgfplots}
\pgfplotsset{compat=1.6,width=6cm}

\lstset{
  basicstyle=\small\ttfamily,
  frame=rltb,
  backgroundcolor=\color{yellow!30},
  breaklines=true,
  escapeinside=||}

\definecollection{myplots}

\makeatletter
\newenvironment{collplot}[2]
  {\@nameuse{collect*}{myplots}{\begin{tikzpicture}}{\end{tikzpicture}}{\lstlisting[caption={#1. (pag.~\pageref{#2})}]}{\endlstlisting}}
  {\@nameuse{endcollect*}}
\makeatother

\begin{document}

\section{The plots}

\begin{figure}[!ht]
\centering
\begin{collplot}{First plot}{fig:testa}
\begin{axis}|\par|
\addplot[domain=-1:100,blue] {sqrt(x)};|\par|
\end{axis}|\par|
\end{collplot}
\caption{First plot}
\label{fig:testa}
\end{figure}

\begin{figure}[!ht]
\centering
\begin{collplot}{Second plot}{fig:testb}
\begin{axis}|\par|               
\addplot[domain=-3:3,red] {x*x};|\par|
\end{axis}|\par|
\end{collplot}
\caption{Second plot}
\label{fig:testb}
\end{figure}

\appendix
\section{The Code}
\includecollection{myplots}

\end{document}

enter image description here

Gonzalo Medina
  • 505,128
6

Here is a solution via filecontents package. Features:

  • the collected code by the coll environment is pure (La)TeX (no |\par| like in Gonzalo Medina's answer).
  • can use several named collections (created by \newcoll).
  • use an external file (\jobname-<collname>-<n>.tex) to store each block of collected code.

Example:

enter image description here

The preamble (with commented macros):

\documentclass[twocolumn]{article}

\makeatletter
% some useful packages
\usepackage{filecontents}
\usepackage{listings}
% utilities
\gdef\coll@currcoll{}
\def\coll@stepcurrcollcount{\stepcounter{coll@count\coll@currcoll}}
\def\coll@currcollcount{\csname thecoll@count\coll@currcoll\endcsname}
\def\coll@currcollshow{\csname thecoll@show\coll@currcoll\endcsname}
\def\coll@currexternfilename{\jobname-\coll@currcoll-\coll@currcollcount}
\def\coll@currlegend{\csname coll@legend\coll@currcoll\coll@currcollcount\endcsname}
\def\coll@setlegend#1{%
  \expandafter\gdef\csname coll@legend\coll@currcoll\coll@currcollcount\endcsname{#1}%
}
\def\coll@getlegend#1{\csname coll@legend\coll@currcoll#1\endcsname}
\def\coll@setref#1{%
  \expandafter\gdef\csname coll@ref\coll@currcoll\coll@currcollcount\endcsname{#1}%
}
\def\coll@getref#1{\csname coll@ref\coll@currcoll#1\endcsname}
% macro to expand collected code into a figure
\newcommand{\coll@execcoll}{%
  \begin{figure}[h!]
    \centering
    \@input{\coll@currexternfilename}%
    \caption{\coll@getlegend{\coll@currcollcount}}
    \label{\coll@getref{\coll@currcollcount}}
  \end{figure}
}
% macro to create a new collection
\newcommand\newcoll[1]{%
  \newcounter{coll@count#1}
  \setcounter{coll@count#1}{0}
  \newcounter{coll@show#1}
  \setcounter{coll@show#1}{0}
}
% environment to add an element to a collection
\newenvironment{coll}[3]{% collection, legend, ref
  \gdef\coll@currcoll{#1}%
  \coll@stepcurrcollcount%
  \coll@setlegend{#2}%
  \coll@setref{#3}%
  \@tempswafalse\filec@ntents%
  {\coll@currexternfilename}%
}
{\endfilecontents\aftergroup\coll@execcoll}
% macro to show one code from current collection
\newcommand{\coll@showonecode}[1]{
  \lstinputlisting[title={Code of figure \ref{\coll@getref{#1}}: \coll@getlegend{#1}}]%
    {\jobname-\coll@currcoll-#1.tex}%
}
% macro to show all collected codes from a collection
\newcommand{\showcoll}[1]{
  \gdef\coll@currcoll{#1}%
  \loop\ifnum\coll@currcollcount>\coll@currcollshow %
    \stepcounter{coll@show#1}
    \coll@showonecode{\coll@currcollshow}
  \repeat
}
\makeatother

The document:

\usepackage{xcolor}
\lstset{
  basicstyle=\small\ttfamily,
  frame=rltb,
  backgroundcolor=\color{yellow!30},
  breaklines=true,
  escapeinside=||
}
\usepackage{tikz}
\begin{document}
\newcoll{code-type-1}
\newcoll{code-type-2}

\section{First section}
\subsection{a subsection}
\begin{coll}{code-type-1}{first legend}{code:one}
\begin{tikzpicture}
  \draw[fill=orange] circle(3mm);
\end{tikzpicture}
\end{coll}

\subsection{another subsection}
\begin{coll}{code-type-2}{another legend}{code:two}
\textbf{bar}
\end{coll}

\section{Second section}
\subsection{third subsection}
\begin{coll}{code-type-1}{third legend}{code:three}
\begin{tikzpicture}
  \draw[fill=blue] circle(3mm) ++(1cm,0) circle(4mm);
\end{tikzpicture}
\end{coll}

\subsection{fourth subsection}
\begin{coll}{code-type-2}{fourth legend}{code:four}
  \begin{tikzpicture}
    \fill[black] circle(5mm and 3mm);
  \end{tikzpicture}
\end{coll}

\section{The collections}
\subsection{Collected codes type 1}
\showcoll{code-type-1}

\subsection{Collected codes type 2}
\showcoll{code-type-2}
\end{document}
Paul Gaborit
  • 70,770
  • 10
  • 176
  • 283