NewEnviron
我想使用用from定义的环境environ
在另一个环境定义中:
\documentclass{article}
\usepackage{environ}
\NewEnviron{inner}[1]{%
\textbf{#1:} \BODY
}
\newenvironment{out}{%
\begin{inner}{Using outer}%
}{%
\end{inner}%
}
\begin{document}
\begin{inner}{Using inner}
Lorem ipsum\ldots
\end{inner}
\begin{out}
Lorem ipsum\ldots
\end{out}
\end{document}
生成的 PDF 看起来符合要求:
但日志显示一些错误:
./test.tex:22: LaTeX Error: \begin{inner} on input line 20 ended by \end{out}.
...
l.22 \end{out}
./test.tex:23: LaTeX Error: \begin{out} on input line 20 ended by \end{document
}.
...
l.23 \end{document}
...
(\end occurred inside a group at level 1)
### semi simple group (level 1) entered at line 20 (\begingroup)
### bottom level
如果我定义out
使用NewEnviron
,那就是
\NewEnviron{out}{%
\begin{inner}{Using outer}%
\BODY
\end{inner}%
}
然后pdflatex
不会终止。
显然,有些东西混淆了(以错误的顺序呈现给解析器)。出了什么问题?
答案1
可以使用环境的命令形式来规避导致错误的环境。因此,尝试
\newenvironment{out}
{% \begin{out}
\inner{Using outer}%
}{% \end{out}
\endinner%
}
正如 egreg 在评论中提到的那样,嵌套\NewEnviron
s 会导致对\BODY
捕获的环境内容宏的循环引用。
答案2
嵌套问题是由于每个定义的(伪)环境都\NewEnviron
用于\BODY
存储内容。
实际上,控制序列名称是可以修改的,但不能在环境启动后修改。可以直接使用\collect@body
或\Collect@Body
,但这会非常麻烦。
我的建议是定义二同一环境的版本:
\newenvironment{innerx}[1]
{\textbf{#1:}}
{}
\NewEnviron{inner}[1]{%
\innerx{#1} \BODY
}
\newenvironment{outx}
{\innerx{Using outer}}
{\endinnerx}
\NewEnviron{out}{\outx~\BODY\endoutx}
当然,在本例中,outx
环境不是必需的,
\NewEnviron{out}{\innerx{Using outer} \BODY\endinnerx}
就足够了。
完整示例:
\documentclass{article}
\usepackage{environ}
\newenvironment{innerx}[1]
{\textbf{#1:}}
{}
\NewEnviron{inner}[1]{%
\innerx{#1} \BODY
}
\newenvironment{outx}
{\innerx{Using outer}}
{\endinnerx}
\NewEnviron{out}{\outx~\BODY\endoutx}
\begin{document}
\begin{inner}{Using inner}
Lorem ipsum\ldots
\end{inner}
\begin{out}
Lorem ipsum\ldots
\end{out}
\end{document}
更新
使用environ
2014 年 5 月 4 日发布的 0.3 版本,可以更轻松地定义嵌套环境\NewEnviron
。当
\environbodyname<control sequence>
找到命令后,\NewEnviron
从该点开始的每个命令都应使用<control sequence>
而不是 来定义\BODY
。以下是基于前面代码的示例。
\documentclass{article}
\usepackage{environ}
\NewEnviron{out}{%
\begin{inner}{Using outer}%
\BODY
\end{inner}%
}
\environbodyname\innerBODY
\NewEnviron{inner}[1]{%
\textbf{#1:} \innerBODY
}
\begin{document}
\begin{inner}{Using inner}
Lorem ipsum\ldots
\end{inner}
\begin{out}
Lorem ipsum\ldots
\end{out}
\end{document}