我想要在循环体中列出清单。例如,写类似
\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}
代替
\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}
那可能吗?
答案1
当 (La)TeX 扫描宏的参数时,它会修复读取的字符/标记的 catcode。因此,当\@whilesw
扫描第二个参数时,所有特殊字符都将被处理为普通的 LaTeX 代码。这与逐字环境相冲突,后者依赖于稍后更改 catcode 来正确排版特殊字符。在这个例子中,这尤其成问题,因为listings
无法再将其识别\end{lstlisting}
为列表的末尾。
一种解决方案是在 catcode 机制下读取列表的代码,其中每个字符都有 catcode 12(其他),因此无需特殊处理。为此,我们可以使用包filecontentsdefmacro
中的环境将代码存储在宏中。第二步是在实际处理该代码时重新应用正常的 catcode 机制,以使环境真正发挥作用。这可以使用 ε-TeX 原语来完成filecontentsdef
\lsttemplate
lstlisting
\scantokens
完整的解决方案如下:
\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}
输出
答案2
与@siracusa 相同的结果,但使用scontents
包(受启发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}