Команда TeX с аргументом ПЕРЕД командой

Команда TeX с аргументом ПЕРЕД командой

Можно ли применить магию TeX, чтобы получить команду \mycmd, которая принимает один аргумент?докоманда и одинпосле. Так что-то вроде <arg1>\mycmd<arg2>. Я попробовал

\documentclass{memoir}
\def#1\mycmd#2{Hello World of #1 and #2}
\begon{document}

{foo}\mycmd{bar}

\end{document}

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

решение1

Проблема была рассмотрена с другой точки зрения вВозможна ли команда с аргументом до и после команды?но ситуация иная: объект, который должен быть помещен до или после основной команды, сам по себе является макросом.

Невозможно иметь макрос, который «смотрит назад». TeX строго «первым пришел, первым вышел» после расширения макроса. Более того, он токенизирует входные данные только тогда, когда это необходимо для предоставления аргументов макросам или примитивам.

После макрорасширения остаются только нерасширяемые токены, и они выполняются в том порядке, в котором они найдены, и удаляются. Таким образом, в такой ситуации, как

{abc}\macro{def}

часть {abc}уже исчезла, когда \macroисследуется. Следы ее могут оставаться в некоторых внутренних списках, так, например, TeX может выполнить , \unskipчто на самом деле является командой, которая при выполнении удаляет последний узел из текущего списка, при условии, что он является клеем (есть волосатые детали, но в целом это правда).

Команда, котораякажетсяделать то, что вы хотите, это \over. Однако, это не макрос, а примитив.

Его работа выполняется на уровне внутренних списков: когда TeX находит \over, он выполняет его, потому что он нерасширяемый. Выполнение заключается в сохранении всего, что есть в текущем математическом списке, в специальном месте и продолжении. Когда конец текущего математического списка найден, TeX использует его и сохраненную часть для построенияФракатом с головным подсписком в качестве числителя и хвостовым подсписком в качестве знаменателя. Но ничего из этого не происходит на уровне макрорасширения.

Тыможетиметь макрос , который смотрит вперед после своего аргумента, чтобы увидеть , появится \firstли макрос , а затем принять соответствующие решения о том, что делать.\second

Даже LuaTeX не может этого сделать, если только вы не измените макропроцессор, поскольку он может проверять и управлять всеми типами узлов в текущем списке, в то время как возможности TeX более ограничены (только штрафы, склейки, керны и блоки, и то не во всех ситуациях).

решение2

Ваши требованиявозможнонапример с encTeX. Попробуйте следующий код, скомпилированный по csplainформату:

\mubyte \phantomcmd #1 {\endmubyte

\mubytein=0
\def\phantomcmd#1\mycmd#2{1=#1, 2=#2}
\def\mycmd{my}
\def\normalcmd#1{normal=#1}

\mubytein=1

\normalcmd{hello}    % gives: normal=hello 
...{foo}\mycmd{bar}  % gives: ...1=foo, 2=bar

\bye

Когда \mubytein=1then активируется специальный ввод: \phantomcmdвставляется перед каждым появлением символа {. Это делается до токена и процессора расширения. Но есть исключение: если сразу {следует за управляющей последовательностью, токенизированной токеновым процессором, то \phantomcmdне вставляется. Поэтому оба примера работают: \normalcmd{hello}и {foo}\cmd{bar}. Второй внутренне работает как:

\phantomcmd{foo}\mycmd{bar}

и это расширяется по желанию. Но эта техника очень хрупкая, потому что каждое появление, {которое не следует сразу за управляющей последовательностью, автоматически предшествует \phantomcmd(когда \mybytein=1). Например, это падает:

\normalcmd {hello}   % this is transformed to \normalcmd\phantomcmd{hello}
bb {foo}\mycmd{bar}  % 

Обратите внимание на разницу между этим и предыдущим примером: пробел сразу после \normalcmd.

Если вас не пугает эта хрупкость, вы можете определить, \pfantomcmdкакие процессы различны \mycmds:

\mubyte \phantomcmd #1 {\endmubyte
\mubytein=0
\def\phantomcmd#1{\def\tmp{#1}}
\def\mycmdA#1{I am A. before: \tmp, after: #1}
\def\mycmdB#1{I am B. before: \tmp, after: #1}
\mubytein=1
... {a}\mycmdA{b} ... {x}\mycmdB{y}
\bye

решение3

В комментарии, сделанном OP, упоминалось, что приложение было одним из предопределенных кавычек перед каллиграфической буквой. Как я сказал в своем ответе на комментарий, возможно, есть некоторая надежда, если проблема может быть более ограниченной. Например, если <arg1>это всегда (и только) один глиф из ограниченного набора возможностей catcode 12, то вы можете достичь желаемого результата, сделав эти глифы \activeи заставив его смотреть вперед, чтобы увидеть, \mycmdследует ли им или нет.

Этот подход можно было бы использовать, если бы не <arg1>требовались возможности внутри других макросов, например, точка ., но он не будет хорошо работать для <arg1>, поскольку он часто используется для указания размеров с помощью десятичной точки.

В MWE <arg1>\mycmd<arg2>выведет Огромный \fbox{<arg1><arg2>}. У меня он настроен только на перехват двойной кавычки или вопросительного знака для , хотя можно добавить <arg1>и другие глифы catcode 12 .<arg1>

ОТРЕДАКТИРОВАНО для игнорирования вызовов с «недопустимыми» значениями <arg1>.

\documentclass{article}
\let\precommand\relax
\let\mycmd\relax
\def\testnext#1#2{\ifx#1\mycmd\myactualcmd\precommand{#2}\else\precommand#1#2\fi}
\def\myactualcmd#1#2{\if#1\precommand\fbox{\Huge#1#2}\else#1#2\fi}
\let\svquote"
\catcode`"=\active
\def"{\let\precommand\svquote\testnext}
\let\svqmark?
\catcode`?=\active
\def?{\let\precommand\svqmark\testnext}

\begin{document}
Is this is a "test"\textbf{?}  This is a "\mycmd{BIG} test?\mycmd{!}

Here mycmd is used with illegal precommand =\mycmd{which} is ignored.
\end{document}

введите описание изображения здесь

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