Populating tabular with etoolbox list
Use \forlistloop
instead:
\documentclass{article}
\usepackage{etoolbox}
\newcommand{\pcodo}[1]{Person: & #1 \\}
\listadd\mylist{Ana}
\listadd\mylist{Bob}
\listadd\mylist{Cole}
\newcommand*{\pco}{\forlistloop{\pcodo}{\mylist}}
\begin{document}
\begin{tabular}{r | l}
\pco
\end{tabular}
\end{document}
There are better ways, though. Here's an implementation that's similar to the one with \xintFor
, but allows for incrementally building the list.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% initialize a list
\NewDocumentCommand{\newlist}{m}
{ % #1=list name
\seq_new:c { g_wasabi_list_#1_seq }
}
% populate a list one item at a time
\NewDocumentCommand{\addtolist}{mm}
{
\seq_gput_right:cn { g_wasabi_list_#1_seq } { #2 }
}
% use a list; "pre" and "post" are code executed before and after the loop
\NewDocumentCommand{\uselist}{mO{}mO{}}
{ % #1=list name, #2=pre, #3=template, #4=post
\cs_gset:Nn \__wasabi_list_temp:n { #3 }
#2
\seq_map_function:cN { g_wasabi_list_#1_seq } \__wasabi_list_temp:n
#4
}
\ExplSyntaxOff
\newlist{my}
%% these commands can go anywhere, provided they are before
%% using the list
\addtolist{my}{Ana}
\addtolist{my}{Bob}
\addtolist{my}{Cole}
\begin{document}
\uselist{my}
[\begin{tabular}{r|l}]
{Person & #1 \\}
[\end{tabular}]
\bigskip
\uselist{my}{#1, }
\end{document}
A list can be used in several ways, with different templates.
With tabular
s, it is often easier to build up (i.e., successively concatenate) a token list and then dump it into the input stream at the end of the process.
\documentclass{article}
\usepackage{etoolbox}
\listadd\mylist{Ana}%
\listadd\mylist{Bob}%
\listadd\mylist{Cole}%
\newtoks\tabtoks
\newcommand*{\pco}{%
\tabtoks{}%
\newcommand*{\ZaZa}[1]{\tabtoks\expandafter{\the\tabtoks Person: & ##1 \\}}%
\forlistloop\ZaZa{\mylist}%
\the\tabtoks%
}
\begin{document}
\begin{tabular}{r | l}
\pco
\end{tabular}
\end{document}
However, thanks to jfbu for noting the problem can be solved more simply than that. The problem with the OP's code is that the &
column separator creates a different scope under \halign
, and so one must work within that constraint of making things globally available to the other tabular
cells. For example, in the OP's original code, merely changing \renewcommand*{\do}[1]{Person: & ##1 \\}
to \gdef\do##1{Person: & ##1 \\}
makes the code produce the proper output. However, thanks to egreg for noting that redefining \do
globally is not acceptable and pointing to \forlistloop
as the optimal alternative.
jfbu proposed the following resolution:
\newcommand*{\pco}{%
\gdef\ZaZa##1{Person: & ##1 \\}%
\forlistloop\ZaZa{\mylist}%
}
resulting in code that works.
\documentclass{article}
\usepackage{etoolbox}
\listadd\mylist{Ana}%
\listadd\mylist{Bob}%
\listadd\mylist{Cole}%
\newcommand*{\pco}{%
\gdef\ZaZa##1{Person: & ##1 \\}%
\forlistloop\ZaZa{\mylist}%
}
\begin{document}
\begin{tabular}{r | l}
\pco
\end{tabular}
\end{document}
Alongside the excellent other two answers, I can propose this one which needs no definition of an extra macro:
\documentclass{article}
\usepackage{xinttools}
\newcommand\mylist{Ana, Bob, Cole}
\begin{document}
\begin{tabular}{r | l}
\xintFor #1 in \mylist \do{Person: & #1 \\}
\end{tabular}
% or \xintFor #1 in {Ana, Bob, Cole}
% or \xintFor* #1 in {{Ana}{Bob}{Cole}}
\end{document}