Estoy intentando aplicar una expl3
función al contenido de un entorno. En LaTeX2e esto se puede lograr usando \bgroup
y \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 \begin
mensajes 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 environ
falló 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 \bgroup
y \egroup
. La versión
\newenvironment{foo}{%
\baz\bgroup
}{%
\egroup
}
\newcommand{\baz}[1]{AAA #1 BBB}
fracasaría exactamente de la misma manera. El argumento \baz
serí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 \NewEnviron
in xparse
debería estar en la lista de tareas pendientes del equipo de LaTeX.
Respuesta2
Esta es una forma de environ
capturarlo \NewEnviron
y \BODY
aplicarlo dentro de un entorno contenedor, definido con xparse
's \NewDocumentEnvironment
, lo que significa que todas las características de xparse
los 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}
Respuesta3
Sabes que quieres usarlo \bar:n
en un entorno para capturar los contenidos. Así que simplemente haga que escanee hacia adelante \end
e inserte \end
nuevamente 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}
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}