LaTeX Optional Arguments

128,954

Solution 1

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.

Solution 2

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

Solution 3

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.

Solution 4

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

Solution 5

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
Share:
128,954

Related videos on Youtube

Verhogen
Author by

Verhogen

Updated on April 20, 2020

Comments

  • Verhogen
    Verhogen about 4 years

    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
    
  • Konrad Rudolph
    Konrad Rudolph over 14 years
    I think the question was about how to determine whether an optional argument was given, not providing a default.
  • Alexey Malistov
    Alexey Malistov over 14 years
    Will! It does not work. Output: (Hello and ) (Hello and Hi)
  • James
    James over 14 years
    Thanks for the feedback, Alexey. I suspect you're using an older version of xparse; there's been a lot of work done on it recently. TeX Live 2009 has just been released :)
  • Crowley
    Crowley over 14 years
    I thought TeX understands as parameters appropriate count of first 'boxes' after command. this 'box' is written in curly braces or it's one symbol. Ie. x^2+1 or x^{2+1} So I have question, does your command test presence of braces? Is it possible to create LaTeX command \sec producing: "A, b,c and d" for command \sec{A}[b,c,d], "A and b" for \sec{A}[b] and "A" for \sec{A}`?
  • Alexey Malistov
    Alexey Malistov over 14 years
    You have two questions. 1) Yes, my command test presence of braces. 2) Yes, it is possible to create macro for \sec{A}[b,c,d] or \sec{A}[b] or \sec{A}.
  • Tanner - reinstate LGBT people
    Tanner - reinstate LGBT people over 11 years
    Although that's true, I found this question while looking for a way to provide a default argument, so this answer was the most useful one for me.
  • loved.by.Jesus
    loved.by.Jesus over 8 years
    I like this approach. Is more "programming-like" and therefore easier to read. Good job!