在 中etoolbox.sty
,三个命令\ifdefmacro
、\ifdefparam
和\ifdefprotected
首先由 定义\newcommand\cmd{}
,然后由 定义\long\edef\cmd{...}
。我不明白为什么\newcommand
那里有空的 s。
我能想到的一个原因是\newcommand\cmd
检查是否\cmd
可定义,因此\cmd
在加载时如果已经定义就会引发错误etoolbox
。那么,是否有其他流行的软件包在历史记录中提供相同的三个命令?另一方面,为什么这三个(并且只有三个)命令很特殊?
更新:@moewe 的回答指出,这样的命令一共有六个,其他三个首先由 定义\newcommand*\cmd{}
。您可以使用类似这样的正则表达式\\newcommand\*?\{\\[a-zA-Z]+\}{}
来匹配所有命令。
答案1
etoolbox
用途\newcommand
或\newrobustcmd
用于全部用户级命令(我猜是为了避免名称冲突)。有些命令的初始定义是空的,\newcommand{\<cmd>}{}
因为它们的实际定义需要\edef
或某些其他\newcommand
未提供的处理。例如
\newrobustcmd
获得一个空的初始定义,因为它需要定义\protected\def
\newcommand*{\newrobustcmd}{}
\protected\def\newrobustcmd{\@star@or@long\etb@new@command}
并\ifdefmacro
最终通过\edef
\newcommand{\ifdefmacro}{}
\long\edef\ifdefmacro#1{%
\noexpand\expandafter\noexpand\etb@ifdefmacro
\noexpand\meaning#1\detokenize{macro}:&}
\edef\etb@ifdefmacro{%
\def\noexpand\etb@ifdefmacro##1\detokenize{macro}:##2&}
\etb@ifdefmacro{\notblank{#2}}
\protecting
需要一个#{
类型“参数”(缺乏更好的术语)
\newcommand*{\protecting}{}
\def\protecting#{%
\ifx\protect\@typeset@protect
\etb@protecting\@firstofone
\fi
\ifx\protect\@unexpandable@protect
\etb@protecting\etb@unexpandable
\fi
\ifx\protect\noexpand
\etb@protecting\unexpanded
\fi
\ifx\protect\string
\etb@protecting\detokenize
\fi
\relax\@firstofone}
\def\etb@protecting#1#2\relax\@firstofone{\fi#1}
\long\def\etb@unexpandable#1{\unexpanded{\protecting{#1}}}
但许多其他宏,比如直接\ifcsmacro
使用\newcommand
\newcommand*{\ifcsmacro}[1]{%
\ifcsdef{#1}
{\expandafter\ifdefmacro\csname#1\endcsname}
{\@secondoftwo}}
内部命令( )通常直接用// ...\etb@...
定义,而不是通过,因为那里不希望出现名称冲突。\def
\edef
\newcommand