Передать тело произвольной среды в подключенную команду

Передать тело произвольной среды в подключенную команду

Я хотел бы внедрить команду в произвольную среду, которая использует тело среды в качестве аргумента.

Желаемое поведение

\begin{AnyEnvironment}{MandatoryEnvArg}[OptionalEnvArg]
  ...
\end{AnyEnvironment}

Следует расширить до

\begin{AnyEnvironment}{MandatoryEnvArg}[OptionalEnvArg]
  \MyMacro{...}
\end{AnyEnvironment}

Где ...находится произвольное содержимое (возможно, включая \pars и другие среды и команды).

Вариант использования

Мой вариант использования для этого, возможно, странного вопроса следующий: я хочу иметь возможность "предварительно обработать" тело окружения с помощью \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}

Связанный контент