可选参数

如何在 LaTeX 中创建带有可选参数的命令? 比如:

\newcommand{\sec}[2][]{
\section*{#1
\ifsecondargument
and #2
\fi}
}
}

然后,我可以称之为

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
138299 次浏览

向导的例子:

\newcommand{\example}[2][YYY]{Mandatory arg: #2;
Optional arg: #1.}


This defines \example to be a command with two arguments,
referred to as #1 and #2 in the {<definition>}--nothing new so far.
But by adding a second optional argument to this \newcommand
(the [YYY]) the first argument (#1) of the newly defined
command \example is made optional with its default value being YYY.


Thus the usage of \example is either:


\example{BBB}
which prints:
Mandatory arg: BBB; Optional arg: YYY.
or:
\example[XXX]{AAA}
which prints:
Mandatory arg: AAA; Optional arg: XXX.

创建“可选参数”背后的基本思想是,首先定义一个中间命令,该命令提前扫描以检测令牌流中接下来出现的字符,然后插入相关的宏来处理出现的参数。使用泛型 TeX 编程可能相当乏味(尽管并不困难)。LaTeX 的 \@ifnextchar对于这类事情非常有用。

对您的问题的最佳答案是使用新的 xparse软件包。它是 LaTeX3编程套件的一部分,包含用于定义带有非常随意的可选参数的命令的广泛特性。

在您的示例中,有一个 \sec宏,它接受一个或两个带括号的参数。将使用 xparse实现这一点,具体做法如下:

\documentclass{article}
\usepackage{xparse}
\begin{document}
\DeclareDocumentCommand\sec{ m g }{%
{#1%
\IfNoValueF {#2} { and #2}%
}%
}
(\sec{Hello})
(\sec{Hello}{Hi})
\end{document}

参数 { m g }定义了 \sec的参数; m表示“强制参数”,g表示“可选的括号参数”。然后可以使用 \IfNoValue(T)(F)检查第二个参数是否确实存在。有关允许的其他类型的可选参数,请参见文档。

你只需要做到以下几点:

\makeatletter
\def\sec#1{\def\tempa{#1}\futurelet\next\sec@i}% Save first argument
\def\sec@i{\ifx\next\bgroup\expandafter\sec@ii\else\expandafter\sec@end\fi}%Check brace
\def\sec@ii#1{\section*{\tempa\ and #1}}%Two args
\def\sec@end{\section*{\tempa}}%Single args
\makeatother


\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi

这是我的尝试,它不完全符合你的规格。没有完全测试,所以要小心。

\newcount\seccount


\def\sec{%
\seccount0%
\let\go\secnext\go
}


\def\secnext#1{%
\def\last{#1}%
\futurelet\next\secparse
}


\def\secparse{%
\ifx\next\bgroup
\let\go\secparseii
\else
\let\go\seclast
\fi
\go
}


\def\secparseii#1{%
\ifnum\seccount>0, \fi
\advance\seccount1\relax
\last
\def\last{#1}%
\futurelet\next\secparse
}


\def\seclast{\ifnum\seccount>0{} and \fi\last}%


\sec{a}{b}{c}{d}{e}
% outputs "a, b, c, d and e"


\sec{a}
% outputs "a"


\sec{a}{b}
% outputs "a and b"

以上所有这些都表明,在 LaTeX 中创建一个漂亮、灵活(或禁止重载)的函数是很困难的! ! !(TeX 代码看起来像希腊语)

好吧,只是为了补充我最近(尽管没有那么灵活)的发展,这里是我最近在我的论文文档中使用的

\usepackage{ifthen}  % provides conditonals...

启动命令,默认情况下将“可选”命令设置为空白:

\newcommand {\figHoriz} [4] []  {

然后让宏设置一个临时变量 temp {} ,这取决于可选参数是否为空。这可以扩展到任何传递的参数。

\ifthenelse { \equal {#1} {} }  %if short caption not specified, use long caption (no slant)
{ \def\temp {\caption[#4]{\textsl{#4}}} }   % if #1 == blank
{ \def\temp {\caption[#1]{\textsl{#4}}} }   % else (not blank)

然后,对于这两种情况,我使用 temp {}变量运行宏。(在这里,如果用户没有指定,它只是将短标题设置为等同于长标题)。

\begin{figure}[!]
\begin{center}
\includegraphics[width=350 pt]{#3}
\temp   %see above for caption etc.
\label{#2}
\end{center}
\end{figure}
}

在本例中,我只检查 newcommand {}提供的单个“可选”参数。如果您要将其设置为,比如说,3个“可选”参数,您仍然必须发送3个空参数... ... 例如。

\MyCommand {first arg} {} {} {}

我知道这听起来很傻,但这就是我对 LaTeX 的看法——一旦我开始研究 TeX 代码,它就不那么有意义了... ... 不过我确实喜欢 Robertson 先生的 xparse 方法,也许我会试试... ..。

我也遇到过类似的问题,当我想创建一个命令 \dx来缩写 \;\mathrm{d}x(即在积分的微分前面加一个额外的空格,并且让“ d”垂直)。但是,我还想使它足够灵活,以便将集成变量作为一个可选参数包含进来。我在序言中加入了以下代码。

\usepackage{ifthen}


\newcommand{\dx}[1][]{%
\ifthenelse{ \equal{#1}{} }
{\ensuremath{\;\mathrm{d}x}}
{\ensuremath{\;\mathrm{d}#1}}
}

然后

\begin{document}
$$\int x\dx$$
$$\int t\dx[t]$$
\end{document}

给出 带可选参数的 dx