How does \renewcommand immediately following a \begin{itemize} prevent missing \item error

Because \do is used at the \begin{document} by the LaTeX kernel to make the \@onlypreamble commands throw an error when used outside the preamble.

The definition of \document contains:

\gdef\do##1{\global\let ##1\@notprerr}%
\@preamblecmds
\global\let \@nodocument \relax
\global\let\do\noexpand % <-- this causes the problem

so \do becomes \noexpand right after \begin{document}, so your \newcommand in the preamble has no effect.

If you put the \renewcommand inside the itemize, when the environment group ends, the previous definition of \do (\noexpand) is restored and this raises the missing \item.

If you move the \renewcommand outside the itemize, its new definition is kept until the second itemize and everything works fine.


Try this:

\documentclass{article}
\usepackage{etoolbox}

\newcommand{\CSVList}{}
\listadd{\CSVList}{a}
\listadd{\CSVList}{b}
\listadd{\CSVList}{c}

\renewcommand*{\do}[1]{\item #1.}%

\begin{document}
    \begin{itemize}
        \renewcommand*{\do}[1]{\item #1.}%
        \dolistloop{\CSVList}%
    \end{itemize}

    \begin{itemize}
\show\do
        \dolistloop{\CSVList}%
    \end{itemize}
\end{document}

The console will show

> \do=\noexpand.
l.18 \show\do

Thus your \do{a} will do

\noexpand\item a

and the output will be, after the “missing \item” error, just

abc

Much better is to define a specific handler:

\documentclass{article}
\usepackage{etoolbox}

\newcommand{\CSVList}{}
\listadd{\CSVList}{a}
\listadd{\CSVList}{b}
\listadd{\CSVList}{c}

\newcommand*{\doCSV}[1]{\item #1.}

\begin{document}

\begin{itemize}
\forlistloop{\doCSV}{\CSVList}
\end{itemize}

\end{document}

I have removed all superfluous % characters.

A different implementation, where the handler is built on the fly; the current item in the list is denoted by #1.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\addtolist}{mm}
 {
  \clist_if_exist:cF { l_grill_list_#1_clist }
   {
    \clist_new:c { l_grill_list_#1_clist }
   }
  \clist_map_inline:nn { #2 }
   {
    \clist_put_right:cn { l_grill_list_#1_clist } { ##1 }
   }
 }
\NewDocumentCommand{\uselist}{mm}
 {
  \cs_set_protected:Nn \__grill_uselist:n { #2 }
  \clist_map_function:cN { l_grill_list_#1_clist } \__grill_uselist:n
 }
\ExplSyntaxOff

\addtolist{CSVList}{a}
\addtolist{CSVList}{b,c}

\begin{document}

\begin{itemize}
\uselist{CSVList}{\item #1.}
\end{itemize}

\end{document}

Tags:

Lists

Itemize