
Gostaria de injetar um comando em um ambiente arbitrário que use o corpo do ambiente como argumento.
Comportamento desejado
\begin{AnyEnvironment}{MandatoryEnvArg}[OptionalEnvArg]
...
\end{AnyEnvironment}
Deveria expandir para
\begin{AnyEnvironment}{MandatoryEnvArg}[OptionalEnvArg]
\MyMacro{...}
\end{AnyEnvironment}
Onde ...
estão conteúdos arbitrários (possivelmente incluindo \par
programas e outros ambientes e comandos).
Caso de uso
Meu caso de uso para esta pergunta talvez estranha é o seguinte: quero ser capaz de "pré-processar" o corpo do ambiente com \MyMacro
. Em particular, \MyMacro
seria um comando que invoca um comando Lua \directlua
que receberia o corpo do ambiente como uma string e realizaria alguma manipulação de string nele antes de colocá-lo de volta no fluxo de entrada do TeX. Como exemplo básico:
\NewDocumentCommand{\MyMacro}{m}
{
\directlua
{
local str = "\luaescapestring{\unexpanded{#1}}"
tex.sprint(str .. ' ~ ' .. str)
}
}
Ainda mais especificamente, tudo isso começou porque eu estava curioso para saber se poderia implementar suporte para sintaxes "abreviadas" (como a usada emtypst
, um programa de composição tipo LaTeX) em modo matemático. Meus experimentos básicos produziram resultados surpreendentemente bons, então fiquei curioso para saber até onde poderia levar esse tipo de funcionalidade no LaTeX, daí a generalidade da minha pergunta.
Requisitos
AnyEnvironment
pode ser qualquer ambiente LaTeX viável. Em particular, pode:- Seja definido pelo usuário.
- Ser definido por pacotes externos.
- Esteja dentro do modo matemático (por exemplo,
aligned
) ou ative o próprio modo matemático (por exemplo,align
). - Tenha qualquer tipo de argumento.
- Pode conter asteriscos (
*
) ou travessões (-
) em seu nome. - Contém conteúdo textual e/ou alterações de código de gato— Parece que apoiar isso seria muito difícil (conforme comentários a esta pergunta).
Abordagens
Redefinindo o ambiente
\let\oldAnyEnvironment\AnyEnvironment
\let\endoldAnyEnvironment\endAnyEnvironment
\RenewDocumentEnvironment{AnyEnvironment}{+b}
{\oldAnyEnvironment\MyMacro{#1}}{\endoldAnyEnvironment}
Problemas:
- Não funciona se
AnyEnvironment
tiver argumentos - Não funciona se
AnyEnvironment
tiver*
(asterisco) ou-
(traço) em seu nome (embora isso possa ser facilmente corrigível, vi ambientes marcados com estrela serem referidos por\<env>star
e\end<env>star
e talvez haja algo semelhante para travessões).
Com ganchos
\ExplSyntaxOn
\NewDocumentCommand { \MyMacro } { m } { Argument:~#1. }
\AtBeginEnvironment { AnyEnvironment } { \MyMacro \bgroup }
\AtEndEnvironment { AnyEnvironment } { \egroup }
\ExplSyntaxOff
Problemas:
- Não funciona;
\bgroup
e\egroup
não são a coisa certa para usar para esse propósito (veja tambémArgumentos possivelmente delimitados por \bgroup e \egroup). No entanto, essa abordagem parece mais promissora para mim. Tentei ler os módulosl3basics
el3quark
, pois tinha esperança de encontrar uma resposta lá; por exemplo,\use_none_delimit_by_q_stop:w ... \q_stop
me fez pensar que talvez algo semelhante pudesse ser usado para coletar o corpo do ambiente. Porém, ainda não consegui encontrar uma solução.
Perguntas relacionadas:
Pacotes relacionados:
environ
– Uma nova interface para ambientes em LaTeX- Define
\BODY
e\Collect@Body
comanda
- Define
xparse
– Um analisador de comando de documento genérico- Define
b
e+b
tipos de argumentos
- Define
amsmath
– Instalações matemáticas AMS para LaTeX- Define
\collect@body
o comando
- Define
Exemplo básico não funcional:
\documentclass{article}
\ExplSyntaxOn
\makeatletter
\NewDocumentEnvironment { AnyEnvironment } {} {} {}
\NewDocumentCommand { \MyMacro } { m } { Contents: ~ #1. }
\AtBeginEnvironment { AnyEnvironment } { \MyMacro \bgroup }
\AtEndEnvironment { AnyEnvironment } { \egroup }
\makeatother
\ExplSyntaxOff
\begin{document}
\begin{AnyEnvironment}
Example.
\end{AnyEnvironment}
\end{document}