Tell me more ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

The \newcommand macro allows to use an optional argument for the first parameter #1 with:

\newcommand{\mycommand}[3][defaultfor1]{blah blah blah}

Is it possible to have more than one option with \newcommand?

share|improve this question

3 Answers

up vote 24 down vote accepted

Try the LaTeX 3 package xparse. Example

\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand{\foocmd}{ O{default1} O{default2} m }{#1~#2~#3}

\begin{document}
  \foocmd{foo} \par
  \foocmd[nondefault1]{foo} \par
  \foocmd[nondefault2][notfoo2]{foo} \par
\end{document}

You may read the documents for more information.

share|improve this answer
Agreed - the flexibility with xparse even allows for an optional starred * version of the command \foocmd by using the s parameter. See the xparse documentation. – Werner Sep 29 '11 at 20:59
Does that also remove the 9 parameters arguments limit? – ℝaphink Sep 29 '11 at 20:59
Note that optional arguments defined by xparse work properly when nested, so \foo[[bar]]{stuff} works to parse [bar] as the optional argument. That is not true for \newcommand. – Joseph Wright Sep 29 '11 at 21:01
2  
@Raphink No, as the underlying mechanism is still TeX based. We really don't want to encourage >9 arguments for any macro: use keyval input! – Joseph Wright Sep 29 '11 at 21:02
Selecting this answer, since it shows a nice example of \DeclareDocumentCommand and egreg already reached rep cap today anyway ;-) – ℝaphink Sep 29 '11 at 21:05

You've got answers for other approaches, so here is the basics using the kernel only. You'll need to define your macros by hand, something like

\makeatletter
\def\mycommand{%
   \@ifnextchar[%
     {\mycommand@i}
     {\mycommand@i[<default-for-1>]}%
}
\def\mycommand@i[#1]{%
   \@ifnextchar[%
     {\mycommand@ii{#1}}
     {\mycommand@ii{#1}[<default-for-2>]}%
}
\def\mycommand@ii#1[#2]#3{%
  % Do stuff
}
\makeatother

This can of course be extended to more complex cases. (Here, I'm leaving it up to you whether to make your function \long or not. If you want part of it to be long, then all of the internal macros should be long. The xparse approach allows this to vary between arguments, based on some internal shuffling.)

share|improve this answer
Thanks, that's interesting. I've seen such constructions in some packages already, but I'd really like to avoid it :-) – ℝaphink Sep 29 '11 at 21:00
I was just writing a solution like this one! – Gonzalo Medina Sep 29 '11 at 21:00
Well I'd just got to the end of this, and was starting on twoopt and xparse, when the other two answers popped up :-) – Joseph Wright Sep 29 '11 at 21:03
\usepackage{twoopt}
\newcommandtwoopt{\xyz}[3][Def1][Def2]{Something with #1, #2 and #3}

There are also \renewcommandtwoopt and \providecommandtwoopt.

However the xparse package (part of the LaTeX3 package tree, but works also with LaTeX2e) provides \DeclareDocumentCommand that gives great flexibility in defining commands with optional arguments in every position and also *-versions.

Historical note

In TeX Live there is a newcommand.py Python script accompanied by documentation accessible by texdoc newcommand. For example, to obtain code for defining a command with two optional arguments and a mandatory one, one launches

python /usr/local/texlive/2011/texmf-dist/doc/latex/newcommand/newcommand.py

and at the prompt % Prototype: answers with

MACRO twoopt OPT[#1={Def1}] OPT[#2={Def2}] #3

where \twoopt is the macro we want to define. The script will build a skeleton for defining the macro:

\makeatletter
\newcommand{\twoopt}[1][Def1]{%
  \@ifnextchar[{\twoopt@i[{#1}]}{\twoopt@i[{#1}][{Def2}]}%
}

\def\twoopt@i[#1][#2]#3{%
  % Put your code here.
  % You can refer to the arguments as #1 through #3.
}
\makeatother

The commented lines should be replaced by the actual code.

With the specification

MACRO finalopt #1 OPT[#2={default}]

one defines a macro with a mandatory argument followed by an optional one:

\makeatletter
\newcommand{\finalopt}[1]{%
  \@ifnextchar[{\finalopt@i{#1}}{\finalopt@i{#1}[{default}]}%
}

\def\finalopt@i#1[#2]{%
  % Put your code here.
  % You can refer to the arguments as #1 and #2.
}
\makeatother
share|improve this answer
@egreg: So twoopt is only limited to two optional arguments I guess? – ℝaphink Sep 29 '11 at 20:59
Yes. See Yan Zhou's answer for more optional arguments. – egreg Sep 29 '11 at 21:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.