为什么 lstlisting 不能保存在命令中?

为什么 lstlisting 不能保存在命令中?

此代码失败,原因如下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 页):

如果您想在参数中使用\lstinlinelstlisting环境,则需要考虑一些事项。由于 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

相关内容