3

I want a listing in the body of a loop. E.g. write something like

\documentclass{article}

\usepackage{listings}

\begin{document}
    \makeatletter
    \lstset{escapechar=|}
    \newcounter{test}
    \@whilesw{\ifnum\value{test}<3}\fi{
        \stepcounter{test}
        \begin{lstlisting}
|\roman{test}|
        \end{lstlisting}
    }
\end{document}

instead of

\documentclass{article}

\usepackage{listings}

\begin{document}
    \lstset{escapechar=|}
    \newcounter{test}
    \stepcounter{test}
    \begin{lstlisting}
|\roman{test}|
    \end{lstlisting}
    \stepcounter{test}
    \begin{lstlisting}
|\roman{test}|
    \end{lstlisting}
    \stepcounter{test}
    \begin{lstlisting}
|\roman{test}|
    \end{lstlisting}
\end{document}

Is that possible?

2 Answers 2

3

When (La)TeX scans the parameter of a macro, it fixes the catcodes of the characters/tokens it reads. So when the second parameter for \@whilesw is scanned, all special characters will be processed as if they were normal LaTeX code. This clashes with verbatim environments which rely on changing catcodes later on to typeset special characters properly. In this example this is especially problematic because listings can't recognoize \end{lstlisting} as the end of the listing anymore.

A solution is to read the listing's code under a catcode regime where every character has catcode 12 (other) and thus handles them in no special way. We can use the filecontentsdefmacro environment from the filecontentsdef package for this purpose to store the code in a macro \lsttemplate. The second step is to re-apply the normal catcode regime when that code is actually processed to make the lstlisting environment actually do its job. This can be done using the ε-TeX primtitive \scantokens

The complete solution looks like this:

\documentclass{article}
\usepackage{listings}
\usepackage{filecontentsdef}

\begin{filecontentsdefmacro}\lsttemplate
\begin{lstlisting}
\roman{test} --> |\roman{test}|
\end{lstlisting}
\end{filecontentsdefmacro}

\begin{document}
    \makeatletter
    \lstset{escapechar=|, basicstyle=\ttfamily}
    \newcounter{test}
    \@whilesw{\ifnum\value{test}<3}\fi{
        \stepcounter{test}
        \scantokens\expandafter{\lsttemplate}
    }
\end{document}

outputs

enter image description here

1
2

Same result as @siracusa, but using the scontents package (inspired by filecontentsdef):

\documentclass{article}
\usepackage{listings}
\usepackage[store-env=lsttemplate]{scontents}

\begin{scontents}
\begin{lstlisting}
\roman{test} --> |\roman{test}|
\end{lstlisting}
\end{scontents}

\begin{document}
    \makeatletter
    \lstset{escapechar=|, basicstyle=\ttfamily}
    \newcounter{test}
    \@whilesw{\ifnum\value{test}<3}\fi{
        \stepcounter{test}
        \getstored[1]{lsttemplate}
    }
\end{document}

You must log in to answer this question.

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