5

I was thinking about a macro with only one argument, but of varibale length expanding the parameters into an enumeration.


E.g.:

  \dostuff{a}

expand to

\begin{enumerate}
  \item a.
\end{enumerate}

and

  \dostuff{a, b, c}

expand to

\begin{enumerate}
  \item a,
  \item b,
  \item c.
\end{enumerate}

Since tex commands can only handle up to 9 arguments, a solution based on a set of arguments would not be a good solution for (and would be an ugly solution as well) i think.

Is there some (hacky?) way to do this?

  • 1
    There a ways of using more than 9 arguments but in this sense it's not recommended! – user31729 Jul 2 '16 at 19:16
6

Using expl3 (the upcoming LaTeX 3 ;-)) this is pretty easy, by using a \seq variable, storing the comma separate list and expanding it with \seq_map_inline:Nn

Since expl3 is pretty stable meanwhile and no really new feature of expl3 is used the following code should work even with an older version of expl3 (I loaded xparse to use \NewDocumentCommand, but a \newcommand would do as well)

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn%

\seq_new:N \l_local_enum_seq

\newcommand{\storethestuff}[1]{%
  \seq_set_from_clist:Nn \l_local_enum_seq {#1}%
}

\newcommand{\dotheenumstuff}{%
\int_zero:N \l_tmpa_int
\seq_map_inline:Nn \l_local_enum_seq {%
    \int_incr:N \l_tmpa_int% Increase the counter
    \item ##1
    % Check whether the list has reached the end -- if so, use '.' instead of ','
    \int_compare:nNnTF 
     { \l_tmpa_int } < {\seq_count:N \l_local_enum_seq} 
     {,} {.}
  }
}

\ExplSyntaxOff


\NewDocumentCommand{\dostuff}{+m}{%
  \storethestuff{#1}%
  \begin{enumerate}
    \dotheenumstuff%
  \end{enumerate}
}

\begin{document}
\dostuff{a,b,c,d,e,f,some more stuff}

\end{document}

enter image description here

The old version with just one command

\documentclass{article}

\usepackage{enumitem}
\usepackage{xparse}

\ExplSyntaxOn%

\seq_new:N \l_local_enum_seq


\NewDocumentCommand{\dostuff}{o+m}{%
  \seq_set_from_clist:Nn \l_local_enum_seq {#2}%
   \int_zero:N \l_tmpa_int
  \IfValueTF{#1}{%
   \begin{enumerate}[#1]
   }{%      
     \begin{enumerate}
    }
   \seq_map_inline:Nn \l_local_enum_seq {%
    \int_incr:N \l_tmpa_int
    \item ##1
    \int_compare:nNnTF { \l_tmpa_int } < {\seq_count:N \l_local_enum_seq} {%
  , } {.}
   }
  \end{enumerate}
 }

 \ExplSyntaxOff


 \begin{document}
 \dostuff[label={Something with spaces}]{a,b,c,d,e,f,some more stuff}

 \end{document}
  • Thanks pretty solution as far as I understand! This is nearly what i want :) could you expand it to my desired commas and the end dot :) – user69453 Jul 2 '16 at 19:05
  • 1
    @user69453: See the update please. – user31729 Jul 2 '16 at 19:13
  • 1
    @ChristianHupfer: Is there a reason of using the two intermediate commands instead of defining it directly in \dostuff? – Tobi Jul 2 '16 at 19:54
  • @Tobi: Take a look at the first version of my post -- some will frown on the first version, others criticise this version ;-) – user31729 Jul 2 '16 at 21:04
  • @ChristianHupfer: Hm … I can’t se a difference … all revisions define \storethestuff and \dotheenumstuff. I’d define only \dostuff to do all the work or at least protect the “internal” macros from users. However if it’s just a question of preference I’m fine. I just wondered if there is a real argument for either version … – Tobi Jul 2 '16 at 21:33
2

expl3 has several features; in this case, \seq_use:Nn seems to be the best choice.

We start enumerate, split the argument at commas (or the character specified in the optional argument, issue \item and then hand each element of the sequence, with ,\item between them. A trailing period ends the job.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_egreg_enum_seq

\NewDocumentCommand{\dostuff}{O{,}m}
 {
  \begin{enumerate}
  \seq_set_split:Nnn \l_egreg_enum_seq {#1} {#2}
  \item
  \seq_use:Nn \l_egreg_enum_seq { , \item }
  .
  \end{enumerate}
 }
\ExplSyntaxOff

\begin{document}

\dostuff{a,b,c,d,e,f,some more stuff}

\dostuff[;]{a; b; c; some, stuff}

\end{document}

enter image description here

1

lualatex solution. Just pass everything as one argument [1] and split on comma. That is all

\documentclass{article}
\IfFileExists{luatex85.sty}{\usepackage{luatex85}}{}

\ifdefined\HCode
\usepackage[utf8]{luainputenc}
\usepackage[T1]{fontenc}
\else
\usepackage{fontspec}
\fi    
\usepackage{luacode}

\begin{luacode*}
function dostuff(arg)
 local str="\\begin{enumerate}"

 for word in string.gmatch(arg, '([^,]+)') do
     str=str.."\\item "..word
 end

 str=str.."\\end{enumerate}"
 tex.print(str)
end 
\end{luacode*}

\newcommand{\dostuff}[1]{\luadirect{dostuff(\luastring{#1})}}

\begin{document}
\dostuff{a,b,c,d,e,f,some more stuff, and $\sin(x)=1$, lualatex is more fun}
\end{document}

Mathematica graphics

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.