¿Es posible hacer algo de magia TeX para obtener un comando \mycmd
que requiera un argumento?antesel comando y unodespués. Entonces algo así como <arg1>\mycmd<arg2>
. Lo intenté
\documentclass{memoir}
\def#1\mycmd#2{Hello World of #1 and #2}
\begon{document}
{foo}\mycmd{bar}
\end{document}
pero obviamente falló. De todos modos, no puedo decir que esperaba que funcionara.
Respuesta1
El problema ha sido examinado desde un punto de vista diferente en¿Es posible un comando con un argumento antes y después del comando?pero la situación es diferente: el objeto que se iba a colocar antes o después del comando principal es en sí mismo una macro.
No es posible tener una macro que “mira hacia atrás”. TeX es estrictamente “el primero en entrar, el primero en salir”, después de la macroexpansión. Además, tokeniza la entrada sólo cuando es necesario para proporcionar argumentos a macros o primitivas.
Después de la macro expansión, solo quedan tokens no expandibles y se ejecutan en el orden en que se encuentran y se eliminan. Entonces en una situación como
{abc}\macro{def}
la {abc}
pieza ya no está cuando \macro
se examina. Su rastro puede quedar en algunas de las listas internas, así, por ejemplo, TeX es capaz de ejecutar \unskip
lo que en realidad es un comando que, al ejecutarse, elimina el último nodo de la lista actual, siempre que esté pegado (hay detalles complicados). , pero esto es básicamente la verdad).
Un comando queparecehacer lo que quieres es \over
. Sin embargo, esto no es una macro, sino una primitiva.
Su trabajo se realiza a nivel de las listas internas: cuando TeX encuentra \over
, lo ejecuta, porque no es expandible. La ejecución consiste en almacenar lo que esté en la lista matemática actual en un lugar especial y continuar. Cuando se encuentra el final de la lista matemática actual, TeX lo usa y la parte almacenada para construir unafracturaátomo con la sublista principal como numerador y la sublista final como denominador. Pero nada de esto sucede a nivel de expansión macroeconómica.
Túpodertener una macro \first
que mira hacia adelante después de su argumento para ver si \second
aparece una macro y luego tomar las decisiones apropiadas sobre qué hacer.
Incluso LuaTeX no puede hacerlo, a menos que modifique el macroprocesador, porque puede examinar y administrar todos los tipos de nodos en la lista actual, mientras que las capacidades de TeX son más limitadas (solo penalizaciones, pegamentos, kerns y cajas y no en todas las situaciones). ).
Respuesta2
Su requisitoes posiblepor ejemplo con encTeX. Pruebe el siguiente código compilado por csplain
formato:
\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
Cuando \mubytein=1
se activa la entrada especial: \phantomcmd
se inserta antes de cada aparición del {
carácter. Esto se hace antes del token y del procesador expandido. Pero hay una excepción: si la {
secuencia de control sigue inmediatamente a la tokenizada por el procesador de tokens, entonces \phantomcmd
no se inserta. Entonces ambos ejemplos funcionan: \normalcmd{hello}
y {foo}\cmd{bar}
. El segundo funciona internamente como:
\phantomcmd{foo}\mycmd{bar}
y esto se amplía según se desee. Pero esta técnica es muy frágil, porque cada aparición que {
no ocurre inmediatamente después de la secuencia de control, está precedida automáticamente por \phantomcmd
(cuando \mybytein=1
). Por ejemplo, esto falla:
\normalcmd {hello} % this is transformed to \normalcmd\phantomcmd{hello}
bb {foo}\mycmd{bar} %
Note la diferencia entre este y el ejemplo anterior: el espacio inmediatamente después \normalcmd
.
Si no temes esta fragilidad, puedes definir \pfantomcmd
qué procesos se realizan entre los distintos \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
Respuesta3
En un comentario realizado por el OP, se mencionó que la aplicación era una de citas predeterminadas previas a una letra caligráfica. Como dije en la respuesta de mi comentario, tal vez haya alguna esperanza si el problema puede limitarse más. Por ejemplo, si <arg1>
siempre (y solo) hay un solo glifo de un conjunto limitado de 12 posibilidades de catcode, entonces podría lograr el resultado deseado creando esos glifos \active
y hacer que mire hacia adelante para ver si \mycmd
los sigue o no.
Este enfoque podría usarse a menos que <arg1>
se necesitaran las posibilidades dentro de otras macros, como el período, .
por ejemplo, no funcionaría bien <arg1>
, ya que se usa frecuentemente para especificar dimensiones mediante un punto decimal.
En el MWE, <arg1>\mycmd<arg2>
se imprimirá un enorme \fbox{<arg1><arg2>}
. Solo lo tengo configurado para interceptar una comilla doble o un signo de interrogación , aunque se podrían agregar <arg1>
otros glifos catcode 12 .<arg1>
EDITADO para ignorar llamadas con valores "ilegales" de <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}