Another expansion issue that I am unable to guess at the correct combination of \edef
/\expandafters
to get to work.
Background:
Below I have defined \AddToCommaSeparateList
which uses \g@addto@macro
as per How keep a running list of strings and then process them one at a time. This works as I desire when used outside of a \foreach
and properly handles list members containing a comma:
Problem:
But when I attempt to add to this list from within a \foreach
, I run into an expansion issue. Well the answer seems pretty obvious, I just need to expand the content that is added to the list. Well, that should not be too difficult, or so I think. So I defined \ExpandedAddToCommaSeparateList
, where instead of
\g@addto@macro#1{{#2}}% used in `\AddToCommaSeparateList`
I simply use:
\edef\ExpandedMember{#2}%
\g@addto@macro#1{{\ExpandedMember}}%
Well, as is usual with expansion issues (at least for me), things did not quite work as expected. In the MWE below I had to resort to an \xdef
to get things to compile, but I should only need an \edef
.
Question:
- What magic combination of
\edef
and/or\expandafter
s do I need to add to the\ExpandedAddToCommaSeparateList
macro so that I can use it outside and inside a\foreach
?
Notes:
- I think this code seems rather long, but I think that is due to the comments, and the first phase which is just to test that the code works as expected in basic usage.
- The problem output is highlighted in red, it should correspond to the output in blue.
- I really just want one version of this macro that works in both cases (inside and outside of a
\foreach
). Don't really see where I would not want expansion (at least in my use case). Hence, am tryinig to handle the expansion issue from within the macro that adds to the list, as opposed to within the\foreach
.
Code:
\documentclass{article}
\usepackage{xcolor}
\usepackage{xstring}
\usepackage{pgffor}
\makeatletter
\newcommand*{\ResetCommaSeparatedList}[1]{\gdef#1{}}%
\newcommand*{\IfEmptyCommaSeparatedList}[3]{%
% #1 = listname
% #2 = code if list is empty
% #3 = code if list is non-empty
\IfStrEq{#1}{}{#2}{#3}%
}
\newcommand*{\AddToCommaSeparateList}[2]{%
% #1 = listname
% #2 = content to add to CSV list
%
% Don't add a leading comma in list
\IfEmptyCommaSeparatedList{#1}{}{\g@addto@macro#1{,}}%
%
% Extra brace group in case #2 contains a comma
\g@addto@macro#1{{#2}}%
}%
\newcommand*{\ExpandedAddToCommaSeparateList}[2]{% with expansion?
% #1 = listname
% #2 = content to add to CSV list
%
% Don't add a leading comma in list
\IfEmptyCommaSeparatedList{#1}{}{\g@addto@macro#1{,}}%
%
% Only need a \edef here, but usign \xdef to get this to compile
\xdef\ExpandedMember{#2}%
% Extra brace group in case #2 contains a comma
\g@addto@macro#1{{\ExpandedMember}}%
}%
\newcommand*{\DumpList}[1][black]{%
\par
MyList = \par
\foreach \x in \MyList {\hspace*{1cm}\textcolor{#1}{\x}\par}
}%
\makeatother
\newcommand*{\MyList}{}%
\begin{document}
\noindent\textbf{Show that this works outside of foreach}\par
\ResetCommaSeparatedList{\MyList}
\AddToCommaSeparateList{\MyList}{1}
\AddToCommaSeparateList{\MyList}{2}
\AddToCommaSeparateList{\MyList}{3}
\AddToCommaSeparateList{\MyList}{4, 5, 6}
\DumpList[blue]
% Repeat just to ensure that that \ResetCommaSeparatedList works
\ResetCommaSeparatedList{\MyList}
\AddToCommaSeparateList{\MyList}{x}
\AddToCommaSeparateList{\MyList}{y}
\AddToCommaSeparateList{\MyList}{z}
\AddToCommaSeparateList{\MyList}{a, b, c}
\DumpList
\bigskip\hrule
\bigskip\noindent
But, when the content is added via a \verb|\foreach| there are
expansion issues.
I want this to yield \textcolor{blue}{1, 2, 3}:
% --------------------------------- Problems start here
\ResetCommaSeparatedList{\MyList}
\foreach \x in {1,...,3} {%
% A check is made here so that only certain ones get added
% to the CSV list (omitted here as it is not relevant to issue)
\ExpandedAddToCommaSeparateList{\MyList}{\x}%
}
\DumpList[red]
\bigskip\noindent
Also, would prefer just one version of this macro, so this should
produce results identical to the first output in blue above:
\ResetCommaSeparatedList{\MyList}
\ExpandedAddToCommaSeparateList{\MyList}{1}
\ExpandedAddToCommaSeparateList{\MyList}{2}
\ExpandedAddToCommaSeparateList{\MyList}{3}
\ExpandedAddToCommaSeparateList{\MyList}{4, 5, 6}
\DumpList[red]
\end{document}