# Writing a multiple option command for a package

I am a newbie at LaTeX programming, so please be patient. :-)

I am writing a .sty file which I want to include a command \dan which is overloaded with three separate versions depending on whether called with zero, one or two arguments.

E.g. I want:

\dan


to generate

Full English

\dan{streaky}


or

\dan{back}


to generate

streaky Bacon

or

back Bacon

respectively, and

\dan{streaky}{fried}


to generate

streaky Bacon with fried Eggs.

"streaky", "fried" etc. are just examples, the users should be able to input any argument.

I have looked into the xparse package, but am finding the documentation inpenetrable. Please can you advise on how to code this?

-
Are you sure that you want that syntax (which you can implement but) It does not follow the pattern of latex syntax which never uses differing numbers of brace groups. LaTeX syntax conventions would make \dan[sreaky,fried] far more preferable. Optional, so [] not {} and taking a comma separated list. –  David Carlisle Mar 12 '12 at 22:53
I'm not fully decided on syntax yet, although I have a preference for the above as I think that will be most natural for the users. Thanks for your point though that optional parameters are usually in [] parentheses, that is something we need to consider - also a comma-separated list is an excellent alternative suggestion. –  dan8394 Mar 12 '12 at 22:59
I recommend to remove your question "Also, is xparse stable enough to use to build a package that you plan to release on CTAN?" from this question and to ask it as a separate question. Also, as you say "I have looked into the xparse package, but am having no success", it's always good to show what you've tried so far. On the one hand, users here can perhaps give you the decisive clue how to go on, on the other hand your question won't be in danger of appearing as a "can i have teh codez plz" question. –  doncherry Mar 12 '12 at 23:10
Thanks doncherry. I have modified my question as you suggested. –  dan8394 Mar 13 '12 at 9:21

This is how.

\documentclass[a4paper]{article}
\usepackage{xparse}

\NewDocumentCommand{\dan}{gg}
{\IfNoValueTF{#2}
{\IfNoValueTF{#1}
{Full English}
{#1 Bacon}%
}
{#1 Bacon with #2 Eggs}%
}

\begin{document}

\dan

\dan{streaky}

\dan{back}

\dan{streaky}{fried}

\end{document}


This said, I advise you against doing so. Users of your package will have a bad time figuring out how to use the commands. Just changing the argument specifier in {oo} instead of {gg} the syntax would be more in line with the LaTeX conventions:

\dan

\dan[streaky]

\dan[back]

\dan[streaky][fried]


If you can be more precise about your intentions, a different strategy may be suggested.

-
This is extremely helpful, and just what I needed. Thanks very much. –  dan8394 Mar 12 '12 at 23:11

As noted in comments I'd recommend using a more conventional LaTeX syntax. @egreg has given a LaTeX3 version, so here's using a loop from LaTeX2e:

\documentclass{article}

\makeatletter

\newcommand\dan[1][full]{%
\def\dansep{\def\dansep{, }}%
\@for\x:=#1\do{%
\dansep
\@nameuse{dan:\x}}}

\@namedef{dan:full}{Full English}
\@namedef{dan:streaky}{Streaky Bacon}
\@namedef{dan:back}{Back Bacon}
\@namedef{dan:fried}{Fried Egg}
\@namedef{dan:mushrooms}{Grilled Mushrooms}

\makeatother

\begin{document}

a \dan

b \dan[streaky]

c \dan[back]

e \dan[streaky,fried]

f \dan[streaky,fried,mushrooms]

\end{document}

-
+1 for \def\dansep{\def\dansep{, }}. The author of etoolbox uses it in other contexts. –  Ahmed Musa Mar 13 '12 at 0:32
I don't think this is what I need. I need to take general arguments, bacon, eggs, etc. are just placeholders. Sorry for not making that clear. –  dan8394 Mar 13 '12 at 9:18
Yes it was clear that it was a toy example, but I also assumed that your real example might require more than two items, which is why I generalised it to an arbitrary list. –  David Carlisle Mar 13 '12 at 9:30

As noted in the comments it is much more preferable to use a key value interface and the answer given by David Carlisle, gives the traditional LaTeX2e way. For more complicated packages, I would lean on using a PGF style of keys. If nothing the amount of users asking questions on this site about TikZ, indicates that there is a large community of users familiar with the PGF style key value interface.

\documentclass{article}
\usepackage[latin]{babel}
\usepackage{pgfkeys}
\begin{document}
%% Step one define family
\pgfkeys{/bacon/.is family}
\pgfkeys{/bacon
type/.store in=\type,
type/.default=streaky,
cook/.store in=\cook,
cook/.default=fried
}
%% Process keys and set defaults, for later use
\def\setdefaults{\pgfkeys{/bacon
type,cook
}%
}
%
\setdefaults
\newcommand{\dan}[2][]{%
\setdefaults
\pgfkeys{/bacon #1}
\def\baconfoods{
\type\ cook \cook,
}
\baconfoods
}
\dan[type=shoulder bacon, cook=well]{}
\dan[type=streaky,cook]{}
\dan[type=streaky]{}
\dan{}
\end{document}


You get tremendous flexibilty with this approach.

-

Here is a solution using catoptions package:

\documentclass{article}
\usepackage{catoptions}
\makeatletter
\newcommand*\dan[1][full]{%
\def\do##1{%
\ifnum\indrisnr>\@ne
,\space\iflastindris and\space\fi
\fi
\uselivecsn{dan:##1}%
}%
\indrisloop{#1}\do
}
% Default inner list parser = , (comma)
% Default outer list parser = ; (semicolon)
\newcommand*\setupdan[2][,;]{%
\def\reserved@a##1##2##3\@nil{%
\def\do####1##1####2##1####3\@nil{%
\csn@edef{dan:\cpttrimspace{####1}}{\cpttrimspace{####2}}%
}%
\def\csv@do####1{\do####1##1##1\@nil}%
\csv@@parse[##2]{#2}%
}%
\reserved@a#1,;\@nil
}
\makeatother

% Example:
\setupdan{%
full,      Full English;
streaky,   Streaky Bacon;
back,      Back Bacon;
fried,     Fried Egg;
mushrooms, Grilled Mushrooms
}

\commentBegin
% The following is also possible:
\setupdan[=,]{%
full       =Full English,
streaky    =Streaky Bacon,
back       =Back Bacon,
fried      =Fried Egg,
mushrooms  =Grilled Mushrooms
}
\commentEnd

\begin{document}
\begin{enumerate}
\item\dan
\item\dan[streaky]
\item\dan[back]
\item\dan[streaky, fried]
\item\dan[streaky, fried, mushrooms]
%\item\dan[xstreaky] % error: undefined
\end{enumerate}
\end{document}


-