环境允许有参数,但对这些参数的引用只能出现在环境的开始代码中,而不能出现在结束代码中。这是什么原因造成的?有没有更好的解决方法?
例如
\newenvironment{foo}[1]%
{some code #1} % allowed
{some code #1} % not allowed
答案1
\newenvironment{foo}[1]%
{...}
{...}
这在内部定义为
\def\foo#1{....}
\def\endfoo{..}
根据定义,结束部分没有任何参数。
\newenvironment{foo}[1]%
{\def\fooNoI{#1}some code #1}
{some code \fooNoI}
答案2
在环境定义的“close”部分不能使用参数的原因很简单:
\newenvironment{foo}[1]
{<start-code>}
{<finish-code>}
实际上做的事情大致相当于
\newcommand{\foo}[1]{<common start-code><start-code>}
\def\endfoo{<finish-code><common finish-code>}
其中所有环境的代码<common>
都相同。因此,#1
在 中使用<finish-code>
将使 TeX#1
在无参数宏的定义中查找,这是非法的。
覆盖此默认行为的最简单方法是使用xparse
:
\usepackage{xparse}
\NewDocumentEnvironment{foo}{m}
{some code #1}
{some code #1}
将按预期工作。必须通过添加尽可能多的标记来指定参数的数量m
。因此将需要两个参数{mm}
。这是因为可以指定其他参数类型(多个位置的可选参数)。有关更多详细信息,请参阅包文档。
答案3
一种解决方法是将信息存储在宏中,然后在环境结束时可以访问该宏。键值选项解析器可能对此很有用。除了图形之外,前列腺素F还提供了相当不错的键值系统,可以与pgfkeys
包一起独立使用。
\documentclass{minimal}
\usepackage{pgfkeys}
\newif\ifbar
\pgfkeys{/mypkg/.is family, /mypkg,
default/.style = {bar=true, foo={not set!}}, % Initialize so 'defaults' exist
foo/.store in = \foo, % Any value assigned to foo will be stored in \foo
bar/.is if = bar, % Declare a boolean, defaults to false
}
\newenvironment{fooenv}[1][]{% Argument is optional as defaults were declared
\pgfkeys{/mypkg/.cd, default, #1}% Shift prefix to `mypkg` and parse arguments
}{%
\textbf{\foo}~
\ifbar
Bar was true!
\else
Bar was false!
\fi
}
\begin{document}
\begin{fooenv}[bar=false, foo={Hello, world!}]
texting...
\end{fooenv}
\begin{fooenv}
Blah blah.
\end{fooenv}
\end{document}
输出结果如下:
发短信...你好世界!酒吧是假的!
啦啦。没有设置!酒吧是真的!
pgfkeys
功能更强大,可与纯 TeX、LaTeX 或 ConTeXt 一起使用。请参阅pgf 手册更多细节。
答案4
我处理这个问题的方式:
\documentclass{article}
\newenvironment{myenv}[1]
{\newcommand{\foot}{#1}{\bfseries Beginning(#1)}: }
{{\bfseries The end (\foot)}}
\begin{document}
\begin{myenv}{Oki doki}
This is my environment, which is quite useless.
\end{myenv}
\end{document}