5

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?

4
  • 3
    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. Mar 12, 2012 at 22:53
  • 1
    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, 2012 at 22:59
  • 3
    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, 2012 at 23:10
  • Thanks doncherry. I have modified my question as you suggested.
    – dan8394
    Mar 13, 2012 at 9:21

4 Answers 4

7

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.

1
  • This is extremely helpful, and just what I needed. Thanks very much.
    – dan8394
    Mar 12, 2012 at 23:11
4

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}
3
  • +1 for \def\dansep{\def\dansep{, }}. The author of etoolbox uses it in other contexts.
    – Ahmed Musa
    Mar 13, 2012 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, 2012 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. Mar 13, 2012 at 9:30
2

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}
%% Define your keys
\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.

1

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}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .