views:

178

answers:

3

I'm experimenting with my own commands and environments and now I'm facing those problems:

  1. How to create command \foo{parameter}[optional] or environment called \begin{bar}{parameter}[optional]?
  2. How to create command \foo[optional_1]...[optional_n]{parameter}

I've tried

\newcommand{\foo}[3][][]{#1#2#3}    - failed
\newcommand{\foo}[3][2][][]{#1#2#3} - failed

Does anyone know some hint? Thanks a lot.

+4  A: 
Antal S-Z
+1 nice summary. A particular issue is if the macro is used incorrectly, with the optional arg being ommitted: "\reversed[optarg]". The error messages will have poor readability with your code: it's worth testing for \reversed@opt being equal to "[" and flagging this as a fatal error if it is.
Charles Stewart
Thanks. I'm not sure what I think about checking for `[`—you're right that it will behave unexpectedly, but it actually has a perfectly well-defined behavior (printing `Required: [; optional: def`, and then typesetting `optarg]`). The *actual* advice I would give is "don't use this technique"—while it's technically possible, it's probably a bad idea.
Antal S-Z
Thank you very much for your time spent on this issue.
Crowley
+3  A: 

Using the xparse package (part of the LaTeX3 development efforts):

\usepackage{xparse}
\NewDocumentCommand\foo{O{}O{}m}{%
  % Code with optional #1 and #2 with empty defaults
}
\NewDocumentCommand\foo{mO{}}{%
  % Code with optional #2 with empty default
}
\NewDocumentEnvironment{foo}{O{}}{%
% Start code with optional #1
}{%
%  End code with optional #1
}

Optional arguments are a bit different in xparse to with \newcommand. You can detect whether one is given or not:

\NewDocumentCommand\foo{mo}{%
  \IfNoValueTF{#2}
   {Code without #2}
   {Code with #2}%
}

You'll see that this works by using a lower case 'o', whereas the upper case 'O' then requires a default value (which I've made empty by including an empty group).

Joseph Wright
I'm sorry for late reply, I did't have time to try it.Thanks a lot for sloving my problem with multiple parameters
Crowley
I've never seen this package before—that's really cool!
Antal S-Z
+2  A: 

Consider also the xargs package. The following is an example from its documentation.

Set it up in the usual way,

\usepackage{xargs}

and then if you define

\newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}

(which means to use "1" for the first argument, if it is not specified, and to use "n" for the third). Then

$\coord{x}$

yields (sans subscripts)

(x1, . . . , xn)

and

$\coord[0]{y}$

yields (again, sans subscripts)

(x0, ..., xn)

dan