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=1特殊输入被激活时:\phantomcmd在每个字符出现之前插入{。这在标记和扩展处理器之前完成。但有一个例外:如果{紧跟在由标记处理器标记的控制序列之后,则\phantomcmd不会插入 。因此两个示例都有效:\normalcmd{hello}{foo}\cmd{bar}。第二个内部工作原理如下:

\phantomcmd{foo}\mycmd{bar}

并且它按预期进行了扩展。但是这种技术非常脆弱,因为每次出现时,它{都不会紧跟在控制序列之后,而是自动以\phantomcmd(when \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>始终(并且仅)是来自有限的 12 种 catcode 可能性集合的单个字形,那么您可以通过制作这些字形来实现所需的结果\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}

在此处输入图片描述

相关内容