5

I'm defining a new command which should take an optional list of arguments (integers or ranges):

\doit[3,5-7,9]{something}

What I have so far:

\def\doit{\@ifnextchar[{\@with}{\@without}}
\def\@with[#1]#2{
  ...
}
\def\@without#1{
}

In the with case, how can I iterate over the optional arguments? How can I distinguish between integers and ranges? Do I need to do the parsing manually or there are tools which can help me?

  • 2
    I bet pgf is able to handle such things. – bodo Jul 27 '12 at 11:20
  • Any pointer or minimal? – Roberto Aloi Jul 27 '12 at 11:31
  • The package etoolbox offers \docsvlist for list-parsing. – clemens Jul 27 '12 at 11:40
7

If changing the - character to ,..., is feasible for you, you can directly and easily benefit from the power of the pgffor module of TikZ/PGF. Please check the manual for other types that are supported. Here is an example with also non-numeric lists:

\documentclass{article}
\usepackage{pgffor}
\makeatletter
\def\doit{\@ifnextchar[{\@with}{\@without}}
\def\@with[#1]#2{
#2 have the following list:%
\foreach \x in {#1}{
\x,%
    }
}
\def\@without#1{
#1, I have no optional arguments.
}
\makeatother

\begin{document}
\doit[1,...,5,7]{I}

\doit{Ahem}

\doit[1,3$\pi$,4$\pi$,...$\pi$,7$\pi$,e,f,...,i]{Also I}
\end{document}

enter image description here

  • 1
    This is so beautiful. – Roberto Aloi Jul 30 '12 at 14:33
5

You can use the splitting argument facilities provided by xparse:

\documentclass{article}
\usepackage{xparse}
\newcommand{\doittemp}{}
\NewDocumentCommand{\doit}{>{\SplitList{,}}om}{%
  \renewcommand\doittemp{#2}%
  \IfNoValueTF{#1}
    {\par (main argument \doittemp)}
    {\ProcessList{#1}{\doitauxi}}%
}
\NewDocumentCommand{\doitauxi}{>{\SplitArgument{1}{-}}m}{\doitauxii #1}
\NewDocumentCommand{\doitauxii}{mm}{%
  \IfNoValueTF{#2}
   {\par Single number #1 (main argument \doittemp)}
   {\par Range #1--#2 (main argument \doittemp)}%
}

\begin{document}
\doit{No optional argument}
\bigskip

\doit[1,2]{Two single numbers}

\bigskip

\doit[1,3-5]{Single number and range}

\bigskip

\doit[1-3,5-10]{Two ranges}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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