
Я хотел бы внедрить команду в произвольную среду, которая использует тело среды в качестве аргумента.
Желаемое поведение
\begin{AnyEnvironment}{MandatoryEnvArg}[OptionalEnvArg]
...
\end{AnyEnvironment}
Следует расширить до
\begin{AnyEnvironment}{MandatoryEnvArg}[OptionalEnvArg]
\MyMacro{...}
\end{AnyEnvironment}
Где ...
находится произвольное содержимое (возможно, включая \par
s и другие среды и команды).
Вариант использования
Мой вариант использования для этого, возможно, странного вопроса следующий: я хочу иметь возможность "предварительно обработать" тело окружения с помощью \MyMacro
. В частности, \MyMacro
это будет команда, которая сама вызывает команду Lua с помощью , \directlua
которая будет получать тело окружения как строку и выполнять некоторые строковые манипуляции с ней перед тем, как поместить ее обратно во входной поток TeX. В качестве простого примера:
\NewDocumentCommand{\MyMacro}{m}
{
\directlua
{
local str = "\luaescapestring{\unexpanded{#1}}"
tex.sprint(str .. ' ~ ' .. str)
}
}
А если говорить точнее, все это началось потому, что мне было интересно, смогу ли я реализовать поддержку «сокращенных» синтаксисов (например, используемых вtypst
, программа набора текста, похожая на LaTeX) в математическом режиме. Мои базовые эксперименты дали на удивление хорошие результаты, поэтому мне стало интересно, насколько далеко я смогу продвинуть эту функциональность в LaTeX, отсюда и общность моего вопроса.
Требования
AnyEnvironment
может быть любая возможная среда LaTeX. В частности, она может:- Определяться пользователем.
- Определяться внешними пакетами.
- Находиться в математическом режиме (например,
aligned
) или активировать сам математический режим (например,align
). - Имейте какие-либо аргументы.
- В названии могут присутствовать звездочки (
*
) или тире ( ).-
- Содержат дословный текст и/или изменения в коде— Похоже, что поддержать это будет очень сложно (судя по комментариям к этому вопросу).
Подходы
Переосмысление окружающей среды
\let\oldAnyEnvironment\AnyEnvironment
\let\endoldAnyEnvironment\endAnyEnvironment
\RenewDocumentEnvironment{AnyEnvironment}{+b}
{\oldAnyEnvironment\MyMacro{#1}}{\endoldAnyEnvironment}
Проблемы:
- Не работает, если
AnyEnvironment
есть аргументы - Не работает, если в названии
AnyEnvironment
есть*
(звездочка) или (тире) (хотя это можно легко исправить, я видел, как отмеченные звездочкой среды обозначаются как и , и, возможно, есть что-то подобное для тире).-
\<env>star
\end<env>star
С крючками
\ExplSyntaxOn
\NewDocumentCommand { \MyMacro } { m } { Argument:~#1. }
\AtBeginEnvironment { AnyEnvironment } { \MyMacro \bgroup }
\AtEndEnvironment { AnyEnvironment } { \egroup }
\ExplSyntaxOff
Проблемы:
- Не работает
\bgroup
и\egroup
не подходит для этой цели (см. такжеАргументы, возможно, разделены \bgroup и \egroup). Однако этот подход кажется мне более многообещающим. Я попытался прочитать модулиl3basics
иl3quark
, так как надеялся, что смогу найти ответ там; например,\use_none_delimit_by_q_stop:w ... \q_stop
заставил меня подумать, что, возможно, что-то похожее можно использовать для сбора тела окружения. Однако мне пока не удалось найти решение.
Похожие вопросы:
Связанные пакеты:
environ
– Новый интерфейс для сред в LaTeX- Определяет
\BODY
и\Collect@Body
командует
- Определяет
xparse
– Универсальный анализатор команд документа- Определения
b
и+b
типы аргументов
- Определения
amsmath
– Математические возможности AMS для LaTeX- Определяет
\collect@body
команду
- Определяет
Простой нерабочий пример:
\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}