假设我有两个命令定义为
\def\witharg#1{something with #1}
\def\without{something without arg}
我想要定义一个新命令\mycmd
,它的行为就像\witharg
后面跟着一个参数(不一定用括号括起来),并且就像\without
后面没有参数一样。事实上,后一种情况只有在后面跟着 token 时才为真\mycmd
。}
为了让事情更清楚一点,我想要
{\mycmd\token\mycmd}
扩展为类似于
{\witharg{\token}\without}
我怎样才能实现这个目标?
请注意,实际上,尝试评估类似的操作{\witharg}
会失败,因为 TeX 会抱怨说有一个多余的,即缺少的}
参数。\witharg
答案1
每当你需要检查宏后面的内容时,通常要使用的原语是\futurelet
(请参阅 TeX by Topic 以获得良好的参考)。在这种情况下,你可以编写类似
\def\mycmd{%
\futurelet\mytoken\myargparse
}
它将\let
以下标记转换为\mytoken
,然后扩展\myargparse
。定义\myargparse
为取决于是什么\mytoken
,就是这样:
\def\myargparse{%
\ifx\mytoken\closingbracetoken
\expandafter\without
\else
\expandafter\witharg
\fi
}
\let\closingbracetoken=}
最后,检查它是否正常工作:
\def\witharg#1{something with #1}
\def\without{something without arg}
\def\token{TOK}
{\mycmd\token\mycmd}
答案2
xparse
可以测试显式括号分隔的参数(或其他分隔符,请参阅文档):
\documentclass{article}
\usepackage{xparse}% http://www.ctan.org/pkg/xparse
\NewDocumentCommand\mycmd{g}{%
\IfValueTF{#1}{(something with #1)}{(something without arg)}%
}
\def\token{TOK}
\begin{document}
\mycmd{Hello}
\mycmd
{\mycmd\token\mycmd}
Blah, \mycmd{Hello}, blah, \mycmd, blah
\end{document}