LaTeX 可选参数

发布于 2024-08-12 23:38:25 字数 278 浏览 5 评论 0原文

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

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

那么,我可以这样称呼它

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

How do you create a command with optional arguments in LaTeX?
Something like:

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

Then, I can call it like

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

救星 2024-08-19 23:38:25

指南中的示例:

\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.

Example from the guide:

\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.
温折酒 2024-08-19 23:38:25

以上所有内容都表明,在 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 方法,也许我我会尝试一下...

All of the above show hard it can be to make a nice, flexible (or forbid an overloaded) function in LaTeX!!! (that TeX code looks like greek to me)

well, just to add my recent (albeit not as flexible) development, here's what I've recently used in my thesis doc, with

\usepackage{ifthen}  % provides conditonals...

Start the command, with the "optional" command set blank by default:

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

I then have the macro set a temporary variable, \temp{}, differently depending on whether or not the optional argument is blank. This could be extended to any passed argument.

\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)

Then I run the macro using the \temp{} variable for the two cases. (Here it just sets the short-caption to equal the long caption if it wasn't specified by the user).

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

In this case I only check for the single, "optional" argument that \newcommand{} provides. If you were to set it up for, say, 3 "optional" args, you'd still have to send the 3 blank args... eg.

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

which is pretty silly, I know, but that's about as far as I'm going to go with LaTeX - it's just not that sensical once I start looking at TeX code... I do like Mr. Robertson's xparse method though, perhaps I'll try it...

葬花如无物 2024-08-19 23:38:25

创建“可选参数”背后的一般思想是首先定义一个中间命令,该命令向前扫描以检测令牌流中接下来出现的字符,然后插入相关宏以适当处理出现的参数。使用通用 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}

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

The general idea behind creating "optional arguments" is to first define an intermediate command that scans ahead to detect what characters are coming up next in the token stream and then inserts the relevant macros to process the argument(s) coming up as appropriate. This can be quite tedious (although not difficult) using generic TeX programming. LaTeX's \@ifnextchar is quite useful for such things.

The best answer for your question is to use the new xparse package. It is part of the LaTeX3 programming suite and contains extensive features for defining commands with quite arbitrary optional arguments.

In your example you have a \sec macro that either takes one or two braced arguments. This would be implemented using xparse with the following:

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

The argument { m g } defines the arguments of \sec; m means "mandatory argument" and g is "optional braced argument". \IfNoValue(T)(F) can then be used to check whether the second argument was indeed present or not. See the documentation for the other types of optional arguments that are allowed.

几度春秋 2024-08-19 23:38:25

当我想创建一个命令 \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 以及可选参数

I had a similar problem, when I wanted to create a command, \dx, to abbreviate \;\mathrm{d}x (i.e. put an extra space before the differential of the integral and have the "d" upright as well). But then I also wanted to make it flexible enough to include the variable of integration as an optional argument. I put the following code in the preamble.

\usepackage{ifthen}

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

Then

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

gives \dx with optional argument

断爱 2024-08-19 23:38:25

您所需要的只是以下内容:

\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

All you need is the following:

\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
喜爱皱眉﹌ 2024-08-19 23:38:25

使用 xargs 包。 请参阅此处的指南

定义示例:

\usepackage{xargs}

\newcommandx{\foo}[3][1=1, 3=n]{...}

用法示例:

\foo[1][2]
\foo[1][2][3]

Use the xargs package. See the guide here.

Example definition:

\usepackage{xargs}

\newcommandx{\foo}[3][1=1, 3=n]{...}

Example usage:

\foo[1][2]
\foo[1][2][3]
数理化全能战士 2024-08-19 23:38:25

这是我的尝试,但它并不完全符合您的规格。尚未完全测试,因此请谨慎。

\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"

Here's my attempt, it doesn't follow your specs exactly though. Not fully tested, so be cautious.

\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"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文