此代码失败,原因如下Emergency stop
:
\documentclass{scrbook}
\usepackage{listings}
\newcommand{\demo}{%
\begin{lstlisting}
foobar
\end{lstlisting}
}
\begin{document}
\demo
\end{document}
为什么?
答案1
在您的代码中,在执行代码之前,整个lstlisting
代码都会作为宏参数读取。当 (La)TeX 读取某些代码时,它会进行一些处理,例如删除注释、将多个空格合并为一个、将换行符转换为空格以及将连续的两个换行符转换为空格\par
等。
但是,lstlisting
环境和所有其他逐字环境或宏都希望所有这些字符(空格、换行符、注释字符)保持其不变的逐字形式。为此,通过改变所谓的类别代码(catcodes),因此 eg%
现在是一个普通字符并且不再启动注释,\
不再启动宏等等。
现在,当代码已经作为宏参数的一部分读取时,所有 catcode 都已分配给字符,并且一些已经如上所述进行了转换,因此之后执行时逐字环境所做的更改不再产生任何影响。
一般来说,有一条规则,即逐字材料不能在宏参数或伪环境(读取其全部内容的环境,例如参见包environ
,但也tabularx
会这样做)中使用。幸运的是,框的读取和处理方式与普通文本相同,因此您可以使用例如环境lrbox
将存储lstlisting
在保存框中,然后稍后使用来使用它\usebox
。但是,您不能使用\sbox
或\savebox
宏,因为它们也将内容读取为宏参数。我编写realboxes
包只是为了提供将内容读取为框的替代方案,因此您可以在加载该包后使用\Sbox
和。\Savebox
答案2
这listings
包裹提供了一些实验性功能,允许您在宏/命令中捕获它。但是,正如包装文档,不建议这样做(部分5.1 参数内的列表,第 46 页):
如果您想在参数中使用
\lstinline
或lstlisting
环境,则需要考虑一些事项。由于 TeX 在执行 -macro 之前读取参数lst
,因此此包无法执行任何操作来保留输入:空格缩小为一个空格,制表符和行尾转换为空格,TeX 的注释字符不可打印,等等。因此,您必须多做一些工作。您必须在以下四个字符前面加上反斜杠:\{}%
。此外,如果 (i) 有两个或多个空格彼此相连,或 (ii) 空格是行中的第一个字符,则必须以相同的方式保护空格。这还不够:每行都必须以“换行符”结束^^J
。而且您无法在这样的列表中转为 LaTeX!... 您可能想知道此功能仍处于实验阶段。原因是:您不应该在参数中使用列表;它并不总是安全的!
因此,可以进行以下操作:
\documentclass{scrbook}
\usepackage{listings}
\newcommand{\demo}{%
\begin{lstlisting}^^J
foobar^^J
\end{lstlisting}
}
\begin{document}
\demo
Some text
\demo
\end{document}
这并不能回答你的问题,但如果你感兴趣的话,它提供了一个不同的解决方法。不确定这通常有多有效,但你可以将一个存放lstlisting
在盒子里(使用lrbox
环境)。也就是说,我不确定是否存在一些可能源于传递给环境的选项的限制lstlisting
。它适用于这种最小的情况。:
\documentclass{scrbook}
\usepackage{listings}% http://ctan.org/pkg/listings
\begin{document}
\newsavebox{\mylisting}
\begin{lrbox}{\mylisting}
\begin{lstlisting}
foobar
\end{lstlisting}%
\end{lrbox}
\usebox{\mylisting}% Print box mylisting
Some text.
\usebox{\mylisting}% Print box mylisting
\end{document}
答案3
@Werner 给出的盒子使用方法的替代方法是使用包scontents
。这允许将内容存储在内存中verbatim
以供以后重复使用(也可以写入外部文件)。
\documentclass{scrbook}
\usepackage{scontents}
\usepackage{listings}
\Scontents*{%
\begin{lstlisting}
foobar
\end{lstlisting}
}
\begin{scontents}
\begin{lstlisting}
barfoo
\end{lstlisting}
\end{scontents}
\begin{document}
Some text
\getstored[2]{contents}
Some text
\getstored[1]{contents}
\getstored[2]{contents}
\end{document}
最好管理环境版本(使用命令版本管理空间有点繁琐)。Saludos