我正在尝试创建一个使用xparse
样式参数的环境,但我必须能够在环境定义中使用整个环境内容,例如作为参数。
理想情况下我想写一些类似的东西
\DeclareCollectedDocumentEnvironment { env } { o } {
Make use of optional Argument #1 and Content \CollectedBody.
}
\begin{env}[optional]
content
\end{env}
有什么原因吗,为什么xparse
不提供这样的东西?
对于我来说,使用\NewEnviron
该environ
包不起作用,因为我依赖于它xparse
提供的一些参数解析功能。
目前我已经完成了这项工作:
\documentclass{article}
\usepackage{xparse}
\usepackage{environ}
\ExplSyntaxOn
\DeclareDocumentCommand { \myenv } { o u\q_nil } {
opt:~#1 \\
content:~#2
}
\cs_set:Npn \myenv_collect:n #1 {
\myenv #1 \q_nil
}
\makeatletter
\DeclareDocumentEnvironment { env } { } {
\Collect@Body \myenv_collect:n
} { }
\makeatother
\ExplSyntaxOff
\begin{document}
\begin{env}[99]
With optional argument
\end{env}
\begin{env}
Without optional argument
\end{env}
\end{document}
但这存在一些缺陷:
- 环境内的多个段落导致无限循环
- 嵌套未按预期工作
我也尝试过声明的参数\DeclareDocumentEnvironment
并以某种方式将它们传递给\myenv_collect:n
,但是的行为\Collect@Body
让这变得困难。
有没有解决我的问题的办法,最好是 latex3 的?
答案1
更新答案(2019 年 3 月)
随着 2019-03-05 版本的发布xparse
, 的功能environ
已实现,并进行了一些调整。 请参阅下面的说明。
上述代码可以简化为
\documentclass{article}
%\usepackage{xparse} % uncomment if you have LaTeX between 2019-03-05 and 2020-09-30
\NewDocumentEnvironment{env}{O{default}+b}
{Do something with #1 and #2}
{}
\begin{document}
\begin{env}
What is this?
Another paragraph.
\end{env}
\begin{env}[foo]
What is this?
Another paragraph.
\end{env}
\end{document}
需要注意的是:参数说明符b
表示环境的主体,然后会像environ
did 一样将其收集为宏参数。没有\BODY
使用:在本例中b
是第二个参数,因此将其称为#2
。
必须指定“结束部分”,尽管它通常是空的。
如果正文中需要段落,则应将参数指定为+b
,就像所有其他“长参数”一样。
原始答案
类似于的接口\NewEnviron
将是一个受欢迎的补充xparse
;但您可以间接使用它:
\documentclass{article}
\usepackage{xparse,environ}
\NewDocumentEnvironment{env}{ O{default} }
{\Environenv{#1}}
{\endEnvironenv}
\NewEnviron{Environenv}[1]
{Do something with #1 and \BODY}
\begin{document}
\begin{env}
What is this?
Another paragraph.
\end{env}
\begin{env}[foo]
What is this?
Another paragraph.
\end{env}
\end{document}
如果您调用 的命令形式Environenv
,它将知道它在什么环境中被调用。这与定义包含 的环境的技巧align
相同amsmath
。