是否可以做一些 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}