如何使用 expl3 将环境内容“双重浸入”到外部文件中?

如何使用 expl3 将环境内容“双重浸入”到外部文件中?

我想捕获特定环境的内容并将它们逐字逐句(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

相关内容