# new command for nested enumerate with variable arguments

I have some text that I want to turn into a template which looks like this:

Extensions:
\begin{enumerate}
\item[2.a] xyz
\begin{enumerate}[i.]
\item a
\item b
\item c
\end{enumerate}
\item[5.b] abc
\begin{enumerate}[i.]
\item x
\item y
\end{enumerate}
\end{enumerate}\\


I want to make a new command that mimics the text above but that takes as arguments something like:

\ucextensions{[2.a] xyz, [5.b] abc}{{a, b, c}, {x, y}}


Please note that I will have variable numbers of arguments. I already have:

\newcommand{\ucextensions}[2]{
Extensions:
\begin{enumerate}
\forcsvlist{\item}{#1 \extensionsteps{#2}}
\end{enumerate}\\
}

\newcommand{\extensionsteps}[1]{
\begin{enumerate}[i.]
\forcsvlist{\item}{#1}
\end{enumerate}
}


which gives output like:

1. [2.a] xyz
2. [5.b] abc
• a, b, c
• x, y

(except with i. and ii. instead of bullets). I would like instead to have output like:

1. [2.a] xyz
• a
• b
• c
2. [5.b] abc
• x
• y

(again with i's instead of bullets). I am using the etoolbox package to do this. Is there a way to do something similar that would take either a nested csv, or a series of csv's to create the desired output?

• Hi and welcome, are you sure you wanna do that? The code base wil be close to non-readable. Will the arguments be generated by some software? Or are they stored in a database? Either way, it might be simpler to program a simple parser, that outputs readable LaTeX code. – Johannes_B Mar 16 '15 at 20:03
• It's actually a template for rapidly writing well-formatted use cases. I want my fellow testers with a minimal understanding of LaTeX to be able to write use cases without having to do a deep dive into lists and things, and moreover to spend a minimum amount of time writing each use case. A parser sounds like it would overly complicate the process. If you have any other suggestions for how to format the input so it would be relatively readable, but use just one command (if possible), I would be seriously appreciative. Super appreciative! I'm in unknown territory for our office here. – jani Mar 16 '15 at 20:42
• I have seen people define one single command with arguments for placement specifier, width, height, file name, label, caption, shortcaption, that are 7 args, to avoid writing down a simple little figure environment. Now, you have to remember which argument is getting which content. I consider that much harder, than retyping and retyping and retyping and or simply defining an editor-macro that inserts the skeleton for me. I can just replace informational content, which in your case could be case label. That is just my personal opinion, though. – Johannes_B Mar 16 '15 at 20:48
• If you want multiple arguments it should definitely be a single {} argument with comma separated values. No latex command takes a variable number of {} arguments. (Although it is technically possible to implement that it would break all latex syntax guidelines) – David Carlisle Mar 16 '15 at 23:05

I'd re-order the input a bit:

\documentclass{article}

\usepackage{enumerate}

\makeatletter
\def\ucextensions#1{%
\begin{enumerate}%
\@for\tmp:=#1\do{\expandafter\ucext\tmp}%
\end{enumerate}}

\newcommand\ucext[2]{%
\item\relax#1\begin{enumerate}[i]%
\@for\tmpb:=#2\do{\item\tmpb}%
\end{enumerate}}

\makeatletter

\begin{document}

\ucextensions{{[2.a] xyz}{a, b, c},
{[5.b] abc}{x, y}
}

\end{document}


I find this kind of input error prone, because the inner list related to an item is placed far from it.

It's possible to get what you want, but perhaps a different syntax can be better.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\ucextensions{mm}
{
\jani_ucextensions:nn { #1 } { #2 }
}

\seq_new:N \l__jani_ucext_outer_seq
\seq_new:N \l__jani_ucext_inner_seq
\seq_new:N \l__jani_ucext_temp_seq
\int_new:N \l__jani_ucext_step_int

\cs_new_protected:Npn \jani_ucextensions:nn #1 #2
{
\seq_set_split:Nnn \l__jani_ucext_outer_seq { , } { #1 }
\seq_set_split:Nnn \l__jani_ucext_inner_seq { , } { #2 }
\int_zero:N \l__jani_ucext_step_int
\par Extensions:
\begin{enumerate}
\seq_map_inline:Nn \l__jani_ucext_outer_seq
{
\item {##1}
\int_incr:N \l__jani_ucext_step_int
\seq_set_split:Nnx \l__jani_ucext_temp_seq { , }
{ \seq_item:Nn \l__jani_ucext_inner_seq { \l__jani_ucext_step_int } }
\begin{itemize}
\item \seq_use:Nn \l__jani_ucext_temp_seq { \item }
\end{itemize}
}
\end{enumerate}
}
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\ExplSyntaxOff

\begin{document}

\ucextensions{[2.a] xyz, [5.b] abc}{{a, b, c}, {x, y}}

\end{document}


I define two sequences, storing the items in the first and second argument, split at commas.

An enumerate environment is opened, then I do a mapping on the first sequence, using the corresponding element in the second sequence, that I again split at commas for building the inner itemize.

A different syntax can be accommodated with a very similar macro for doing the job.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\ucextensions}{m}
{
\group_begin:
\jani_ucextensions:n { #1 }
\group_end:
}

\seq_new:N \l__jani_ucext_outer_seq
\seq_new:N \l__jani_ucext_inner_seq
\seq_new:N \l__jani_ucext_temp_seq
\int_new:N \l__jani_ucext_step_int

\keys_define:nn { jani/ucext }
{
ext  .code:n = \seq_put_right:Nn \l__jani_ucext_outer_seq { #1 },
spec .code:n = \seq_put_right:Nn \l__jani_ucext_inner_seq { #1 },
}

\cs_new_protected:Npn \jani_ucextensions:n #1
{
\keys_set:nn { jani/ucext } { #1 }
\int_zero:N \l__jani_ucext_step_int
\par Extensions:
\begin{enumerate}
\seq_map_inline:Nn \l__jani_ucext_outer_seq
{
\item {##1}
\int_incr:N \l__jani_ucext_step_int
\seq_set_split:Nnx \l__jani_ucext_temp_seq { \\ }
{ \seq_item:Nn \l__jani_ucext_inner_seq { \l__jani_ucext_step_int } }
\begin{itemize}
\item \seq_use:Nn \l__jani_ucext_temp_seq { \item }
\end{itemize}
}
\end{enumerate}
}
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\ExplSyntaxOff

\begin{document}

\ucextensions{
ext  = [2.a] xyz,
spec =  a \\ b \\ c,
ext  = [5.b] abc,
spec = x \\ y
}

\end{document}


Each extension should be followed by its specifications, so it's impossible to forget something.

The output is exactly the same.