5

I was trying to use recursion in LaTeX to create a list of items. I don't have much experience with LaTeX so kindly explain any uncommon commands used. Here's my code for the same.

\makeatletter

\newcommand\@itemsi{\@ifnextchar\stopitems{}{\@add}}

\newcommand\@add[1]{
  \item #1
  \@itemsi
}

\newcommand\@newitems{
    \begin{itemize}
    \@itemsi
    \end{itemize}
}

\makeatother

This is the output I'm getting using this code

\@newitems
{Fruits}
{Vegetables}
{Drink}
\stopitems

Output: newitemsFruitsVegetablesDrink

I instead want this,

  • Fruits
  • Vegetables
  • Drink
Milap
  • 313

3 Answers3

4

Recursive Approach

See also the giggles at the bottom for a generic implementation. :)

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\quark_new:N \StopItems

\cs_new:Nn \milap_new_items: { \begin{itemize} \milap_next_item:n }
\cs_new:Nn \milap_next_item:n {
  \tl_if_eq:nnTF {#1} {\StopItems}
    { \end{itemize} }
    { \item #1 \milap_next_item:n }
}

\NewDocumentCommand \NewItems { } {
  \milap_new_items:
}
\ExplSyntaxOff

\begin{document}
\NewItems
  {hello}
  {there}
  {world}
\StopItems
\end{document}

Idiomatic expl3 (in my opinion)

Using xparse to grab all the arguments and expl3 to work with them:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand \NewItems { u{\StopItems} } {
  \tl_set:Nn \l_tmpa_tl {#1}
  \begin{itemize}
    \tl_map_inline:Nn \l_tmpa_tl { \item ##1 }
  \end{itemize}
}
\ExplSyntaxOff

\begin{document}
\NewItems
  {hello}
  {world}
\StopItems
\end{document}

Comma-Separated List

For completion :)

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand \NewItems { m } {
  \clist_set:Nn \l_tmpa_clist {#1}
  \begin{itemize}
    \clist_map_inline:Nn \l_tmpa_clist { \item ##1 }
  \end{itemize}
}
\ExplSyntaxOff

\begin{document}
\NewItems{hello,world}
\end{document}

Giggles

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\quark_new:N \StopItems

\cs_new:Nn \milap_new_items:nn { \begin{#1} \milap_next_item:nnn {#1} {#2} }
\cs_new:Nn \milap_next_item:nnn {
  \tl_if_eq:NNTF {#3} {\StopItems}
    { \end{#1} }
    { \item #3 \milap_next_item:nnn {#1} {#2} }
}

\NewDocumentCommand \NewItems { O{itemize} O{\item} } {
  \milap_new_items:nn {#1} {#2}
}
\ExplSyntaxOff

\begin{document}
\NewItems[enumerate]
  {hello}
  {there}
  {world}
\StopItems
\end{document}
Sean Allred
  • 27,421
  • It should be \tl_if_eq:nnTF, shouldn't it? Also \StopItems should probably be defined as a quark: \quark_new:N \StopItems – egreg May 05 '15 at 22:50
  • @egreg Hmm, yes it should; I must have gotten a little too happy with my shift key :) And you're absolutely right! \StopItems is definitely a quark here. – Sean Allred May 05 '15 at 22:52
  • @egreg Is it appropriate to define \StopItems as a quark when it's used in a u-type xparse argspec? – Sean Allred May 05 '15 at 22:55
  • In the case of a delimiter it's irrelevant: it can even be undefined. – egreg May 05 '15 at 23:09
  • @egreg Given how I think u is implemented, that makes sense :) – Sean Allred May 05 '15 at 23:13
  • Thanks for writing all the different methods. I wasn't aware about the xparse package. Can you please explain what \cs_new and \tl_if_eq commands do? – Milap May 05 '15 at 23:22
  • 1
    @MilapSheth xparse is great :) Read up on texdoc xparse for more goodies. As for the other things, I'll refer you to texdoc interface3 for the full documentation, but \cs_new: and \tl_if_eq: are expl3 functions. expl3 is the (very well-organized) programming layer with which LaTeX3 is being built. The two functions correspond roughly to \def and \ifx, respectively. Note that everything after the : is part of the function name, too. expl3 has a different syntax to it, toggled with \ExplSyntaxOn/Off (analogous to \makeatother/letter). – Sean Allred May 06 '15 at 00:05
4
\documentclass{article}

\begin{document}

\makeatletter% don't use @ for commands intended for document use....



\newcommand\@newitems{\begin{itemize}\@itemsi}


\def\@itemsi#1{%
  \ifx\stopitems#1%
    \end{itemize}\expandafter\@gobble
  \else
    \item#1\expandafter
  \fi
  \@itemsi}


This is the output I'm getting using this code

\@newitems
{Fruits}
{Vegetables}
{Drink}
\stopitems

\end{document}
David Carlisle
  • 757,742
  • Thanks for your answer. It's pretty concise. Though since I'm a bit new to LaTeX can you explain what \expandafter does here? I know it takes the token after the next one but it's not clear to me how that's used here – Milap May 05 '15 at 23:30
  • 1
    @MilapSheth see http://tex.stackexchange.com/questions/107753/why-the-expandafter-firstoftwo-idiom/ – David Carlisle May 05 '15 at 23:59
1

Taken from iterate over commaseparated list

Add this to your preamble and call inside document with

\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newcommand\makeitemize[1]{%
  \begin{itemize}
    \forcsvlist{\makeitemize@item}{#1}
  \end{itemize}
}
\newcommand\makeitemize@item[1]{\item #1}
\makeatother

\begin{document}
\makeitemize{A,B,C} 
\end{document}
  • Your solution do not work in a simple article document like \documentclass{article} \begin{document} Test \end{document} Can you provide a MWE? – Fran May 05 '15 at 19:56
  • @DavidCarlisle you are right. I have corrected my answer and learned, to test code bevor submit to the community. This will never happen again. – Peter Ebelsberger May 06 '15 at 08:09
  • @PeterEbelsberger thanks for updating (original comment deleted) – David Carlisle May 06 '15 at 08:49