我想捕获特定环境的内容并将它们逐字逐句(n
- 类型扩展)复制到已设置为iow
输出流的外部文件中。
我的第一个想法是简单地创建并使用一个标记列表变量,如下所示:
\tl_new:N \l_resume_position_contents_tl
\NewDocumentEnvironment { position } { m } {
...
\tl_set:Nn \l_resume_position_contents_tl
\group_begin:
} {
\group_end:
\resume_do_stuff_with:N \l_resume_position_contents_tl
\tl_use:N \l_resume_position_contents_tl
}
但我收到了错误
! Missing } inserted.
<inserted text>
}
l.71 \end{position}
我认为这是由于对\group_?:
功能的完全误解。有没有更简单的方法可以解决这个问题?
答案1
除了执行与包类似的操作之外,没有其他方法可以将环境的内容吸收为令牌列表environ
。
当你输入时\tl_set:Nn \l_resume_position_contents_tl {...}
,你告诉 TeX 要做
\edef\l_resume_position_contents_tl{\unexpanded{...}}
除特殊情况外,相当于
\def\l_resume_position_contents_tl{...}
TeX 的语法规则要求两个括号都是明确的;更具体地说,\def
(或\edef
)必须后面跟着一个控制序列(或活动字符);在控制序列之后,直到找到明确的{
1 个标记,才会找到“参数文本”(在本例中为空)。找到括号后,TeX 开始将其找到的标记存储为替换文本,并跟踪括号嵌套,无需做任何扩展直到到达与左括号匹配的显式}
2标记。此时宏的替换文本已被吸收,TeX 执行分配。
在这种情况下,\edef
还有一个额外的步骤:在将新的含义分配给控制序列之前,被吸收的替换文本会得到充分扩展。
因此任何尝试
\newenvironment{foo}[1]
{\def#1\bgroup}
{\egroup}
注定会失败,因为\bgroup
不是显式的{
1标记,所以它将被视为参数文本的一部分;让我们看一个简单的例子:
\begin{foo}{\baz}
Something
\end{foo}
当 LaTeX 发现\begin{foo}
它本质上确实如此时\begingroup\foo
,其中的定义\foo
在这种情况下是
\def\foo#1{\def#1\bgroup}
替换后我们有
\def\baz\bgroup Something\end{foo}
哦,不!我们将其定义\baz
为具有\bgroup Something\end
参数文本和foo
替换文本。环境将绝不完成。
使用\group_begin:
不是一个解决方案,因为\begingroup
当语法规则需要它(显式或隐式)时,它永远不能替代开括号。
那么,你能做什么呢?使用environ
,因为目前xparse
不提供类似的功能:
\usepackage{environ}
\ExplSyntaxOn
\tl_new:N \l_resume_position_contents_tl
\NewEnviron { position } [1]
{...
\tl_set_eq:NN \l_resume_position_contents_tl \BODY
\resume_do_stuff_with:N \l_resume_position_contents_tl
\tl_use:N \l_resume_position_contents_tl
}
\ExplSyntaxOff