定义一个扩展 verbatim 环境的新环境

定义一个扩展 verbatim 环境的新环境

为什么不能定义一个扩展verbatim环境的新环境?考虑一下,例如:

\documentclass{article}
\newenvironment{myverbatim}{\tiny\begin{verbatim}}{\end{verbatim}}
\begin{document}
\begin{myverbatim}
  test
\end{myverbatim}
\end{document}

编译时pdflatex出现错误:

Runaway argument?
^^M  test^^M\end{myverbatim}^^M\end{document}^^M^^M
! File ended while scanning use of \@xverbatim.
<inserted text> 
                \par

(这个问题的动机可以在这里找到:“格式化逐字段落“。从中应该可以清楚的是,我不能使用listingsfancyvrb包)

如果能提供基本的、甚至更详细的解释(针对这种特殊情况和错误信息的原因)就更好了,比如,在这个讨论中给出的解释是这样的:“为什么 verbatim 不起作用......“,并且是否可以针对像本例中这样的简单情况找到解决方法……

编辑1:

根据目前的答案,我觉得我需要更精确地说明我的情况:我试图让以下代码以某种方式工作(请咨询“格式化逐字段落“ 更多细节)

\documentclass{article}
\makeatletter
\begingroup
  \catcode`|=0
  \catcode`[=1
  \catcode`]=2
  \catcode`\{=12
  \catcode`\}=12
  \catcode`\\=12
  |gdef|myvr@xverbatim#1\end{myverbA}[#1|end[myverbA]]
|endgroup
\newenvironment{myverbA}{%
  \let\@xverbatim=\myvr@xverbatim
  \verbatim
}{%
}
\makeatother
\newenvironment{myverbB}{\tiny\begin{myverbA}}{\end{myverbA}}
\begin{document}
\begin{myverbB}
  test
\end{myverbB}
\end{document}

编辑2:

根据egreg的回答,我尝试了以下操作:

\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\begingroup
  \catcode`|=0
  \catcode`[=1
  \catcode`]=2
  \catcode`\{=12
  \catcode`\}=12
  \catcode`\\=12
  |gdef|myvr@xverbatim#1\end{myverbA}[#1|end[myverbA]]
|endgroup
\newenvironment{myverbA}{%
  \let\@xverbatim=\myvr@xverbatim
  \verbatim
}{%
}
\newenvironment{myverbB}
  {\preto\verbatim@font{\tiny}
   \myverbA}
  {\endmyverbA}
\makeatother
\begin{document}
\begin{myverbB}
  test
\end{myverbB}
\end{document}

会产生错误:

Runaway argument?
^^M  test^^M\end{myverbB}^^M\end{document}^^M^^M
! File ended while scanning use of \@xverbatim.
<inserted text> 
                \par 

答案1

使用你的定义的主要问题myverbatim可以通过范围和宏替换的组合来定义。也就是说,以

\begin{<some-env>}

预计将结束

\end{<some-env>}

如果没有,那就有问题了,因为范围没有明确定义。在你的例子中,你从

\begin{myverbatim}

内部替换为(\tiny暂时删除字体更改)

\begin{verbatim}

现在,由于您已处于verbatim环境中(即成功调用\begin{verbatim}),LaTeX 开始吞噬内容并按原样打印它们直到它得到一行类似于的代码

\end{verbatim}

这就是verbatim环境的工作方式。它正在寻找停止点。但是,这种情况永远不会发生,因为在环境中永远不会将\end{myverbatim}(在您的代码中)替换为\end{verbatim}(根据您的定义)verbatimverbatim不会将宏替换为其定义。因此,TeX 只是继续扫描,产生被认为是“失控参数”的错误。

考虑到上述情况,从广泛的角度来看,替代方案会使您的 MWE 类似于(我添加了一条评论):

\documentclass{article}
\newenvironment{myverbatim}{\tiny\begin{verbatim}}{\end{verbatim}}
\begin{document}
\tiny\begin{verbatim}% Replacement text for \begin{myverbatim}
  test
\end{myverbatim}% No replacement since you're in the verbatim environment
\end{document}

显然,上述内容并不是从相同的环境开始和结束的。

如果您想要更灵活verbatim,请使用verbatim包裹它允许您执行以下操作:

在此处输入图片描述

\documentclass{article}
\usepackage{verbatim}% http://ctan.org/pkg/verbatim
\newenvironment{myverbatim}%
  {\endgraf\tiny\verbatim}%
  {\endverbatim}
\begin{document}
Some text before.
\begin{myverbatim}
test
test
\end{myverbatim}
Some text after.
\end{document}

verbatim包是获得所需解决方案的一种手段,就像fancyvrblistings会。当然,更基本的实现(特定于您的情况)是仅更改verbatim宏中存储的字体\verbatim@font

\makeatletter
\renewcommand{\verbatim@font}{\tiny\ttfamily}
\makeatother

当然,您也可以在verbatim环境前面加上它\tiny,它也能正常工作,但\verbatim@font它是在verbatim环境内调用的,因此只能在环境内运行,而不能在环境之外运行。

答案2

它不起作用,因为

\documentclass{article}
\newenvironment{myverbatim}{\tiny\begin{verbatim}}{\end{verbatim}}
\begin{document}
\begin{myverbatim}
  test

\不再是一个转义字符,它的作用与输入\. 完全相同,因此:

\end{myverbatim}

并不是结束环境的命令,它只是更多的文本,因此这也是:

\end{document}

TeX 到达文件末尾,然后事情就出错了。

正常verbatim结束,因为它专门查找字符串\end{verbatim} 并停止。该字符串不在您的文档中。

verbatim和包fancyvrb提供了定义逐字环境的功能。

答案3

问题在于发出命令的时间。如果没有前面的命令,\tiny它就不能在前面,但也不能在后面。\verbatim\par

因此,您必须改变的定义\verbatim@font

\documentclass{article}
\usepackage{verbatim,etoolbox}
\makeatletter
\newenvironment{myverbA}
  {\verbatim}
  {\endverbatim}
\newenvironment{myverbB}
  {\preto\verbatim@font{\tiny}
   \myverbA}
  {\endmyverbA}
\makeatother

\usepackage{lipsum}

\begin{document}
\lipsum*[3]% no \par is issued
\begin{myverbB}
  test
\end{myverbB}
\lipsum*[3]
\begin{myverbA}
another test
\end{myverbA}
\end{document}

在此处输入图片描述

您可能还想看看这个fancyvrb包:

\documentclass{article}
\usepackage{fancyvrb}
\newenvironment{myverbA}
  {\Verbatim}
  {\endVerbatim}
\newenvironment{myverbB}
  {\myverbA[fontsize=\tiny]}
  {\endmyverbA}

\usepackage{lipsum}

\begin{document}
\lipsum*[3]% no \par is issued
\begin{myverbB}
  test
\end{myverbB}
\lipsum*[3]
\begin{myverbA}
another test
\end{myverbA}
\end{document}

答案4

您可以在这里找到答案带有保留 LaTeX 符号的特殊文本命令或者,如果您不介意盒子中的结果(我的意思是 LaTeX 盒子,而不是有边框的盒子),您可以使用verbatimbox带有可选参数的包:

\documentclass{article}
\usepackage{verbatimbox}
\begin{document}
\begin{verbbox}[\tiny]
This is tiny \verbatim
\end{verbbox}
\theverbbox
\end{document}

相关内容