Equivalente a \bgroup \egroup en LaTeX3

Equivalente a \bgroup \egroup en LaTeX3

Estoy intentando aplicar una expl3función al contenido de un entorno. En LaTeX2e esto se puede lograr usando \bgroupy \egroup. En expl3, algo no funciona.

Esperaría que el siguiente código imprima "AAA hey BBB". En cambio, imprime "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}

¿Alguna idea sobre por qué sucede esto y posibles soluciones?

Editar

Este es mi enfoque actual:

\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

Esto no funcionará, ya que \group_begin: y \group_end: no se pueden usar para capturar argumentos de funciones (es decir, \foo \group_begin: A \group_end:funciona de manera diferente a \foo { A }).

¿Hay alguna manera de forzar temporalmente a una secuencia de control a comportarse como si fuera una llave explícita?

Una solución

Creo que tengo una solución. Como mencioné en los comentarios, se podría combinar la coincidencia de patrones con contar el número de \beginmensajes para capturar el contenido de un entorno. Fue un poco sorprendente para mí que esto fueraprecisamente¿Qué está pasando en environ, justo debajo de unLOTEde notación.

Como sé que environfalló en mi aplicación prevista, decidí volver a implementarlo de la manera más simple posible, para poder descubrir dónde falla mi código (ahora tengo una idea de qué salió mal, pero ese no es el punto). A continuación puede encontrar una implementación en expl3. No lo he probado a fondo, pero creo que funciona.

Cualquier comentario o reseña es muy apreciada.

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

Respuesta1

TienenuncaHa sido posible conseguir una discusión con \bgroupy \egroup. La versión

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

fracasaría exactamente de la misma manera. El argumento \bazsería \bgroup, por lo que la salida de

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

sería

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

Uno de los espacios inesperados proviene del final de línea después de \begin{foo}, el otro del final de línea después de key.

Es posible utilizar environ, como lo muestra 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

y el resultado del código anterior sería el esperado

xAAA<space>key<space}BBBy

Agregar funciones similares a \NewEnvironin xparsedebería estar en la lista de tareas pendientes del equipo de LaTeX.

Respuesta2

Esta es una forma de environcapturarlo \NewEnvirony \BODYaplicarlo dentro de un entorno contenedor, definido con xparse's \NewDocumentEnvironment, lo que significa que todas las características de xparselos especificadores de argumentos aún se pueden usar.

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

ingrese la descripción de la imagen aquí

Respuesta3

Sabes que quieres usarlo \bar:nen un entorno para capturar los contenidos. Así que simplemente haga que escanee hacia adelante \ende inserte \endnuevamente al final del texto de reemplazo.

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

ingrese la descripción de la imagen aquí

Respuesta4

Francamente, no sé si funcionará una vez que se reescriba todo el paquete, pero al menos ahora puedo entender lo que está pasando. Existen algunas limitaciones: los entornos definidos tienen solo dos parámetros. #1 representa el contenido del entorno; #2 representa un parámetro entre corchetes, que en principio se puede utilizar para contener valores-clave y así superar esta limitación.

Además, mis entornos funcionan con los comandos \xbegin{\foo} y \xend{\foo}. La estructura subyacente de estos comandos es diferente a la de los entornos LaTeX, por lo que decidí usar palabras clave diferentes. De todos modos, supongo que el enfoque podría ampliarse para aplicarse a entornos LaTeX.

¡Cualquier revisión o comentario sobre el código es muy bienvenido y 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}

información relacionada