8

I want to create a macro that yields an inline lists. I can easily do this using enumerate* form the the enumitem package, but when I attempt to wrap this in a macro, I get:

Extra }, or forgotten \endgroup.
\item ...ctor \relax \fi }\color@endgroup \egroup 
                                                  \enit@outeritem 

Code:

\documentclass{article}
\usepackage[inline]{enumitem}
\usepackage{pgffor}

\newlist{MyHChoices}{enumerate*}{2}
\setlist*[MyHChoices]{label=\Alph*., itemjoin={\hspace*{2.0em}}}

\newcommand*{\InlineList}[1]{%
    \MyHChoices
        \foreach \Choice in {#1} {%
            \item \Choice
        }%
    \endMyHChoices
}%


\begin{document}
\begin{MyHChoices}
    \item One
    \item Two
    \item Three
\end{MyHChoices}

%\InlineList{One, Two, Three}% ???
\end{document}

2 Answers 2

8

Token register method

The problem is that the list environment is not too happy, if \item is put inside a group. \foreach of pgffor puts the body inside groups.

The following file uses a token register to collect the body of the environment. \Choice needs to be expanded once.

\documentclass{article}
\usepackage[inline]{enumitem}
\usepackage{pgffor}

\newlist{MyHChoices}{enumerate*}{2}
\setlist*[MyHChoices]{label=\Alph*., itemjoin={\hspace*{2.0em}}}

\newtoks\gInlineToks
\newcommand*{\InlineList}[1]{%
    \global\gInlineToks{}%
    \foreach \Choice in {#1} {%
        \global\gInlineToks\expandafter{%
            \the\expandafter\gInlineToks
            \expandafter\item\Choice
        }%
    }%
    \begin{MyHChoices}\the\gInlineToks\end{MyHChoices}%
}%

\begin{document}
\begin{MyHChoices}
    \item One
    \item Two
    \item Three
\end{MyHChoices}

\InlineList{One, Two, Three}
\end{document}

Package kvsetkeys

An alternative approach for pgffor:

\documentclass{article}
\usepackage[inline]{enumitem}
\usepackage{kvsetkeys}

\newlist{MyHChoices}{enumerate*}{2}
\setlist*[MyHChoices]{label=\Alph*., itemjoin={\hspace*{2.0em}}}

\makeatletter
\newcommand*{\InlineList}[1]{%
  \begin{MyHChoices}%
    \comma@parse{#1}\InlineListItem
  \end{MyHChoices}%
}
\newcommand*{\InlineListItem}[1]{%
  \item #1%
}
\makeatother


\begin{document}
\begin{MyHChoices}
    \item One
    \item Two
    \item Three
\end{MyHChoices}

\InlineList{One, Two, Three}
\end{document}
6

You may try this, which seems shorter than Heiko's:

\documentclass{article}
\usepackage[inline]{enumitem}
\usepackage{xparse}

\newlist{MyHChoices}{enumerate*}{2}
\setlist*[MyHChoices]{label=\Alph*., itemjoin={\hspace*{2.0em}}}

\ExplSyntaxOn
\NewDocumentCommand{\InlineList}{ m }
 {
  \begin{MyHChoices}
  \clist_map_inline:nn { #1 } { \item ##1 }
  \end{MyHChoices}
 }
\ExplSyntaxOff

\begin{document}
\begin{MyHChoices}
    \item One
    \item Two
    \item Three
\end{MyHChoices}

\InlineList{One, Two, Three}     
\end{document}

If you plan to use a different delimiter than the comma, the usual "split and store in a sequence" strategy is quite easy to follow:

\ExplSyntaxOn
\NewDocumentCommand{\InlineList}{ O{,} m }
 {
  \begin{MyHChoices}
  \peter_process_hchoices:nn { #1 } { #2 }
  \end{MyHChoices}
 }

\seq_new:N \l__peter_hchoices_seq

\cs_new_protected:Npn \peter_process_hchoices:nn #1 #2
 {
  \seq_set_split:Nnn \l__peter_hchoices_seq { #1 } { #2 }
  \seq_map_inline:Nn \l__peter_hchoices_seq { \item ##1 }
 }
\ExplSyntaxOff

With this block instead of the previous one, you can input your list as

\InlineList{One, Two, Three}

\InlineList[;]{One; Two; Three}

\InlineList[/]{One / Two/ Three}

and get identical results.

You must log in to answer this question.

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