相当于 LaTeX3 中的 \bgroup \egroup

相当于 LaTeX3 中的 \bgroup \egroup

我正在尝试将expl3函数应用于环境的内容。在 LaTeX2e 中,这可以通过使用\bgroup和来实现\egroup。在 中expl3,有些东西不起作用。

我期望以下代码打印“AAA hey BBB”。相反,它打印“AAA BBB hey”。

\ExplSyntaxOn

\cs_new:Npn \bar:n #1 {
    AAA #1 BBB
}

\NewDocumentEnvironment{foo}{}{
    \bar:n \bgroup
}{
    \egroup
}

\ExplSyntaxOff

\begin{document}

\begin{foo}
    hey
\end{foo}

\end{document}

对于为什么会发生这种情况以及可能的解决方法有什么想法吗?

编辑

这是我目前的方法:

\cs_new:Npn \env_new:Nn #1#2 {
    \tl_new:N #1
    \tl_set:Nn #1 { #2 }
}

\cs_new:Npn \env_begin:N #1 {}
\cs_new:Npn \env_end:N #1 {}

\cs_new:Npn \env_capture_on: {
    \global \let \env_begin:N \group_begin:
    \global \let \env_end:N   \group_end:
}

\cs_new:Npn \env_capture_off: {
    \global\let\env_begin:N\env_original_begin:N
    \global\let\env_end:N\env_original_end:N
}

\cs_new:Npn \env_original_begin:N #1 {
    \env_capture_on:
    \tl_use:N #1
    \group_begin:
    \env_capture_off:
}

\cs_new:Npn \env_original_end:N #1 {
}

\env_capture_off:


\cs_new:Npn \foo:n #1 {
    AAA #1 BBB
}

\env_new:Nn \baf {
    \foo:n
}

\env_begin:N \baf
    hey
\env_end:N \baf

这将不起作用,因为 \group_begin: 和 \group_end: 不能用于捕获函数参数(即,\foo \group_begin: A \group_end:工作方式与 不同\foo { A })。

有没有什么方法可以暂时强制控制序列表现得像一个明确的括号?

一个办法

我认为我有一个解决方案。正如我在评论中提到的,可以将模式匹配与计数结合起来\begins 的数量结合起来,以捕获环境的内容。这让我有点惊讶,这是恰恰发生了什么事environ,就在很多的符号。

因为我知道environ在我的预期应用程序中失败了,所以我决定以最简单的方式重新实现它,这样我就可以找出我的代码在哪里失败了(现在我知道哪里出了问题,但这不是重点)。您可以在下方找到一个实现expl3。我还没有彻底测试过它,但我相信它是有效的。

非常感谢您的任何评论或评价。

\int_new:N \env_count
\cs_new:Npn \env_new:Nn #1#2 {
    \cs_new:cpn { env_defined@ \cs_to_str:N #1 :nn } ##1##2 {
        #2
    }
}

\cs_new:Npn \env_countbegin:w #1\xbegin#2 {
    \cs_if_free:NTF #2 {
        \int_incr:N \env_count
        \env_countbegin:w
    } {
        \cs_if_eq:NNTF #2 \xend {} {
            \int_incr:N \env_count
            \env_countbegin:w
        }
    }
}

\cs_new:Npn \env_collect:w #1#2#3#4\xend#5 {
    \env_countbegin:w #4\xbegin\xend
    \int_compare:nTF { \env_count = 0 } {
        \use:c { env_defined@ \cs_to_str:N #1 :nn } { #3 #4 } { #2 }
    }{
        \int_decr:N \env_count
        \env_collect:w {#1} {#2} { #3 #4 \xend{#5} }
    }
}

\NewDocumentCommand \xbegin {mo} {
    \int_zero:N \env_count
    \env_collect:w {#1} {#2} {}
}

\NewDocumentCommand \xend {} {}

\env_new:Nn \foo {
    AAA #1 BBB
}

\xbegin{\foo}
\xbegin{\foo}
hey
\xend{\foo}
\xend{\foo}

答案1

它有绝不\bgroup有可能抓住一个论点\egroup。版本

\newenvironment{foo}{%
  \baz\bgroup
}{%
  \egroup
}
\newcommand{\baz}[1]{AAA #1 BBB}

会以完全相同的方式失败。的参数将\baz\bgroup,因此

x\begin{foo}
key
\end{foo}y

将会

xAAA<space><space>BBB<space>key<space>y

其中一个意外空格来自 之后的行尾\begin{foo},另一个来自 之后的行尾key

可以使用environ,如 Christian Hupfer 所示:

\usepackage{xparse,environ}

\ExplSyntaxOn
\NewEnviron{foo}
 {
  \jaeya_baz:V \BODY
 }

\cs_new:Nn \jaeya_baz:n { AAA~#1~BBB }
\cs_generate_variant:Nn \jaeya_baz:n { V }
\ExplSyntaxOff

上述代码的输出将是预期的

xAAA<space>key<space}BBBy

\NewEnviron添加类似的功能xparse应该列在 LaTeX 团队的待办事项清单上。

答案2

这是一种使用 和 的方法environ,在用定义的包装器环境中\NewEnviron捕获并应用它,这意味着- 参数说明符的所有功能仍然可以使用。\BODYxparse\NewDocumentEnvironmentxparse

\documentclass{article}
\usepackage{environ}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new:Nn \bar:n {
  AAA #1 BBB
}


\NewEnviron{foointernal}{
  \bar:n {\BODY}
}

\ExplSyntaxOff

\let\origfoointernal\foointernal
\let\origendfoointernal\endfoointernal

\NewDocumentEnvironment{foo}{}{%
  \origfoointernal%
}{%
  \origendfoointernal%
}

\begin{document}

\begin{foo}
    hey
\end{foo}


\begin{foo}
   \blindtext

   Hello World
\end{foo}

\end{document}

在此处输入图片描述

答案3

\bar:n您知道您想在环境中使用它来获取内容。因此,只需让它向前扫描\end\end再次插入替换文本的末尾即可。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new:Npn \bar:n #1 \end {
    AAA #1 BBB \end
}

\NewDocumentEnvironment{foo}{}{\bar:n}{}

\ExplSyntaxOff

\begin{document}

\begin{foo}
    hey
\end{foo}

\end{document}

在此处输入图片描述

答案4

坦白说,我不知道整个包重写后它是否还能正常工作,但至少现在我能理解发生了什么。有几个限制:定义的环境只有两个参数。#1 表示环境的内容;#2 表示方括号参数,原则上可用于包含键值,从而克服此限制。

此外,我的环境使用命令 \xbegin{\foo} 和 \xend{\foo}。这些命令的底层结构与 LaTeX 环境不同,因此我决定使用不同的关键字。无论如何,我猜这种方法可以扩展到适用于 LaTeX 环境。

非常欢迎并感谢对代码的任何审查或评论!

\documentclass[10pt]{article}
\usepackage{expl3}

\ExplSyntaxOn

\int_new:N \env_count
\cs_new:Npn \env_new:Nn #1#2 {
    \cs_new:cpn { env_defined@ \cs_to_str:N #1 :nn } ##1##2 {
        #2
    }
}

\cs_new:Npn \env_countbegin:w #1\xbegin#2 {
    \cs_if_free:NTF #2 {
        \int_incr:N \env_count
        \env_countbegin:w
    } {
        \cs_if_eq:NNTF #2 \xend {} {
            \int_incr:N \env_count
            \env_countbegin:w
        }
    }
}

\cs_new:Npn \env_collect:w #1#2#3#4\xend#5 {
    \env_countbegin:w #4\xbegin\xend
    \int_compare:nTF { \env_count = 0 } {
        \use:c { env_defined@ \cs_to_str:N #1 :nn } { #3 #4 } { #2 }
    }{
        \int_decr:N \env_count
        \env_collect:w {#1} {#2} { #3 #4 \xend{#5} }
    }
}

\NewDocumentCommand \xbegin {mo} {
    \int_zero:N \env_count
    \env_collect:w {#1} {#2} {}
}

\NewDocumentCommand \xend {} {}

\env_new:Nn \foo {
    AAA #1 BBB
}

\ExplSyntaxOff

\begin{document}    

\xbegin{\foo}
\xbegin{\foo}
hey
\xend{\foo}
\xend{\foo}

\end{document}

相关内容