Equivalente para \bgroup \egroup em LaTeX3

Equivalente para \bgroup \egroup em LaTeX3

Estou tentando aplicar uma expl3função ao conteúdo de um ambiente. No LaTeX2e isso pode ser conseguido usando \bgroupe \egroup. Em expl3, algo não funciona.

Eu esperaria que o código a seguir imprimisse "AAA ei BBB". Em vez disso, imprime "AAA BBB ei".

\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}

Alguma idéia de por que isso acontece e possíveis soluções alternativas?

Editar

Esta é minha abordagem atual:

\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

Isso não funcionará, já que \group_begin: e \group_end: não podem ser usados ​​para capturar argumentos de funções (ou seja, \foo \group_begin: A \group_end:funcionam de maneira diferente de \foo { A }).

Existe alguma maneira de uma sequência de controle ser temporariamente forçada a se comportar como se fosse uma chave explícita?

Uma solução

Acho que tenho uma solução. Como mencionei nos comentários, pode-se combinar a correspondência de padrões com a contagem do número de \begins para capturar o conteúdo de um ambiente. Foi um pouco surpreendente para mim que isso sejaprecisamenteo que está acontecendo em environ, logo abaixo de umMUITOde notação.

Como sei que isso environfalhou na aplicação pretendida, decidi reimplementá-lo da maneira mais simples possível, para poder descobrir onde meu código falhou (agora tenho uma ideia do que deu errado, mas esse não é o ponto). Abaixo você pode encontrar uma implementação em expl3. Não testei completamente, mas acredito que funciona.

Quaisquer comentários ou críticas são extremamente apreciados.

\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}

Responder1

Temnuncafoi possível argumentar com \bgroupe \egroup. A versão

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

falharia exatamente da mesma maneira. O argumento para \bazseria \bgroup, então a saída de

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

seria

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

Um dos espaços inesperados vem do final de linha depois de \begin{foo}, o outro do final de linha depois de key.

É possível usar environ, como mostra 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

e a saída do código acima seria a esperada

xAAA<space>key<space}BBBy

Adicionar recursos semelhantes a \NewEnvironeste xparsedeve estar na lista de tarefas da equipe LaTeX.

Responder2

Esta é uma maneira de environand \NewEnviron, capturá-lo \BODYe aplicá-lo em um ambiente wrapper, definido com xparse's \NewDocumentEnvironment, o que significa que todos os recursos dos xparseespecificadores de argumento ainda podem ser usados.

\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}

insira a descrição da imagem aqui

Responder3

Você sabe que deseja usar \bar:nem um ambiente para capturar o conteúdo. Portanto, basta digitalizar adiante \ende inserir \endnovamente no final do texto de substituição.

\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}

insira a descrição da imagem aqui

Responder4

Sinceramente, não sei se funcionará depois que todo o pacote for reescrito, mas pelo menos agora posso entender o que está acontecendo. Existem algumas limitações: os ambientes definidos possuem apenas dois parâmetros. #1 representa o conteúdo do ambiente; #2 representa um parâmetro entre colchetes, que em princípio pode ser usado para conter valores-chave e assim superar essa limitação.

Além disso, meus ambientes funcionam com comandos \xbegin{\foo} e \xend{\foo}. A estrutura subjacente desses comandos é diferente daquela dos ambientes LaTeX, então decidi usar palavras-chave diferentes. De qualquer forma, acho que a abordagem poderia ser estendida para ser aplicada a ambientes LaTeX.

Qualquer revisão ou comentário sobre o código é extremamente bem-vindo e apreciado!

\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}

informação relacionada