具有一个或两个参数的宏

具有一个或两个参数的宏

我正在尝试定义一个具有可变参数数量的宏。例如,我想定义一个具有两个参数的宏,该宏也可以使用一个参数。因此,同一个宏可以以两种方式工作。

\textcolor{red}{sample text}

这会将红色限制在示例文本中,而只需调用\textcolor{red}即可将红色一直打开到文档末尾。因此,使用宏的第二种方法是

\textcolor{red}

我尝试使用 来实现宏\@ifnextchar。但并没有取得太大成功。您能给我一些提示吗?

根据@Joseph 的建议,我修改了我的玩具代码,它运行正常。我仍然无法理解代码中的实际执行流程。这是我的代码。

\documentclass[12pt]{article}
\makeatletter
\def\oneortwoargs#1{%
\@ifnextchar\bgroup%
   {\twoargs@aux{#1}}
   {\onearg@only{#1}}
}

\def\onearg@only#1{%
   Only argument provided: #1 %
}

\def\twoargs@aux#1#2{%
   Two arguments are provided. \\%
   First argument: #1 \\ %
   Second argument: #2%
}
\makeatother

\begin{document}
\oneortwoargs{gg}{fff}
\oneortwoargs{qq}
\end{document}

正如@Joseph 在下面解释的那样,输入流中只剩下一个标记。令我困惑的是\onearg@only\twoargs@aux以相同的方式调用,并且只有一个参数。

答案1

我会用xparse包来执行此操作,因为所有内容都是“预先打包的”:

\documentclass{article}
\usepackage{color,xparse}
\NewDocumentCommand\MyTextColor{m+g}{%
  \IfNoValueTF{#2}
    {\color{#1}}
    {\textcolor{#1}{#2}}%
}
\begin{document}
\MyTextColor{green}{stuff}

\MyTextColor{red} Some text
\end{document} 

当然也可以使用\@ifnextchar

\documentclass{article}
\usepackage{color}
\makeatletter
\newcommand*\MyTextColor[1]{%
  \@ifnextchar\bgroup
    {\textcolor{#1}}
    {\color{#1}}%
}
\makeatother
\begin{document}
\MyTextColor{green}{stuff}

\MyTextColor{red} Some text
\end{document} 

关键点是您需要寻找{使用\bgroup而不是尝试直接使用它(因为它是 begin-group 字符)。


为了解释该\@ifnextchar部分如何处理需要 1 个或 2 个参数的情况,我的第二种方法是

\newcommand*\MyTextColor[1]{%

定义一个吸收的宏论点。所以:

\MyTextColor{red}{stuff}

吸收red#1{stuff}在输入流中,而

\MyTextColor{red} other stuff

也吸收red#1other stuff在输入流中。我们现在应用\@ifnextchar,它“偷看”下一个标记不吸收. 测试内容

  \@ifnextchar\bgroup
    {\textcolor{#1}}
    {\color{#1}}%

因此,根据结果,要么\textcolor{red}要么\color{red}被插入到输入流中。因此,我们最终得到

\textcolor{red}{stuff}

或者

\color{red} other stuff

这意味着\textcolor将获取所需的两个参数,而\color只获取一个参数。关键是{red}重新插入\textcolor在或之后输入\color


虽然与问题没有直接关系,但对该xparse方法的一些注释可能会有用。使用该xparse包时,参数用字母描述,m表示强制参数,g用 表示可选参数,用大括号 (IE一个可选的 TeX 组)。+字母前面的 A 允许该参数接受段落标记,因此在我的定义中,第一个参数不能(它应该是一个颜色的名称),而第二个参数可以(它是任意文本)。

如果可选参数根本不存在,则参数将返回一个特殊标记 ( )。如果需要默认值,我会使用。g同样的方法适用于标准 LaTeX 可选参数,它们表示为或,具体取决于是否需要默认值。我已经使用测试;和进行了测试。\NoValueG{<default>}oO\NoValue\IfNoValueTF\IfNoValueT\IfNoValueT

答案2

在 ConTeXt 中,你可以使用 定义这样的宏\dodoublegroupempty。例如:

\def\TwoArgMacro
  {\dodoublegroupempty\doTwoArgMacro}

\def\doTwoArgMacro#1#2%
  {\ifsecondargument
      Two arguments were passed: #1 and #2
    \else
      One argument was passed: #1
    \fi}

其工作原理是检查下一个字符是否等于\bgroup

相关内容