I was really pleased that I could come up with a means of building the contents of a tabular environment using \foreach \x in {...} {...} structure.
But I was curious about what exactly it would take to break my code. Here's my preamble, which works for generally non-complex content (whatever that's supposed to mean):
\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{amsmath,amssymb,array}
\usepackage{booktabs}
\usepackage{etoolbox}
\usepackage{pgfkeys,pgffor}
\pgfkeys{/ae/agenda/.cd,
items for the agenda/.initial=,
title/.initial=,
}
\def\aeset#1{\pgfkeys{/ae/agenda/.cd,#1}}
\def\aeget#1{\pgfkeysvalueof{/ae/agenda/#1}}
\makeatletter
\newcounter{agendaitemcounter}
\def\agenda@item@number{%%
\stepcounter{agendaitemcounter}%%
\arabic{agendaitemcounter}.)}
\def\full@agenda{}
\long\def\build@agenda{%%
\foreach \x in \list@of@agenda@items {
\xdef\full@agenda{%%
\expandonce\full@agenda
\expandonce\agenda@item@number
\expandonce\aeamp
\expandonce\x
\noexpand\\
\noexpand\midrule}
}}
\def\setagenda#1{%%
\bgroup
\aeset{#1}%%
\edef\list@of@agenda@items{\aeget{items for the agenda}}%%
\build@agenda
\begin{minipage}[t]{4in}\centering
{\large \aeget{title}}%%
\par\vspace{1ex}
\begin{tabular}{cp{3in}}\toprule
\full@agenda \bottomrule
\end{tabular}%%
\end{minipage}%%
\setcounter{agendaitemcounter}{0}%%
\egroup
\def\full@agenda{}%%
}
\makeatother
\renewcommand{\arraystretch}{1.5}
\def\aeamp{&}
\def\aepar{\par}
\def\dollars#1{\$#1}%$
\def\mypoly{\[x^2+1\]}
\pagestyle{empty}
So, I started playing with things to see where the macros in the preamble would break: it wasn't too hard to find something.
The example code below compiles fine as written with the above preamble (except for the one commented-out line that contains \noexpand\par).
However, if I start removing \noexpand commands from these working lines, errors start popping up.
What I can't quite understand is why certain structures don't break (e.g. \frac{...}{...}, x^2, and \infty) while other---superficially similar or simpler?---structures (e.g. \cos or \$) do break my code.
\begin{document}
\setagenda{
title={To-do list},
items for the agenda={%%
{Line of random content, but nothing too fancy.},
{Not too involved math: $x\cdot y$ },
{A bit more involved, but it works! $\displaystyle{}\frac{1}{2d}$ },
{ Random collection of math symbols: $\inf \infty x^2+x$ },
%% I need to use `\noexpand` to avoid getting an error.
{This line works!\noexpand\aepar Hello world }
%%{This line fails!\noexpand\par Hello world }
{ what follows fails without \noexpand\texttt{noexpand}},
{ Trying something which covers multiple lines
\belowdisplayskip=0pt%%
\belowdisplayshortskip=0pt%%
\noexpand\mypoly
},
{Transfer \noexpand\dollars{3000} for trip to Venice},
{ $x\noexpand\cos(x)$ How many suitcases do I need?},
{ What's this going to result in?
\belowdisplayskip=0pt%%
\belowdisplayshortskip=0pt%%
\noexpand\[ x^2+1\noexpand\]
}
}%%
}
\vspace{1cm}
\setagenda{
title={something else},
items for the agenda={%%
{first item},
{second item}}}
\end{document}
Why is it that some math commands work and others don't. I thought that, because I'm issuing \expandonce in the macro used to build the contents of the tabular environment, these errors shouldn't arise.
To labor the point a bit more, when I try to look at this in miniature, without all the noise of the tabular environment, I get even more confused.
The following MWE compiles fine:
\documentclass{article}
\usepackage{etoolbox}
\usepackage{pgffor}
\begin{document}
\let\mytrial\relax
\foreach \x in {$\cos$,
$x^2+x$}
{\xdef\mytrial{\x}}
\mytrial
\end{document}
So, there's nothing inherently evil about \cos and \xdef being used together. But when I try to make this look a bit more like the code above in \setagenda, things go awry in ways I can't quite fathom.
\documentclass{article}
\usepackage{etoolbox}
\usepackage{pgffor}
\begin{document}
\let\mytrial\relax
\foreach \x in {$\cos$,
$x^2+x$}
{\xdef\mytrial{\mytrial\x}}
\mytrial
\end{document}
I don't even get an error. TeX just enters an infinite loop (it's as though there's a LaTeX3'ish quark in there or something).
Well, I have \let something to be \relax in there. So, I tried
\documentclass{article}
\usepackage{etoolbox}
\usepackage{pgffor}
\begin{document}
\def\mytrial{\relax}
%%\def\mytrial{}%%<--- this line works too!
\foreach \x in {$\cos$,
$x^2+x$}
{\xdef\mytrial{\mytrial\x}}
\mytrial
\end{document}
which does work, which totally flabbergasts me! How is this last example any different from what I'm doing inside \setagenda? There aren't even any \expandonce commands in there to save things for later.
My understanding of \noexpand\x is that
\xdef\mycmd{\noexpand\somecmd}
results in
\mycmd=\somecmd
My understanding of \expandonce\x where \x=\noexpand\cos is that
\xdef\mycmd{\expandonce\x}
results in
\mycmd=\noexpand\cos
So if I've got something like
\mycmd=\noexpand\cos
\x=\noexpand\tan
and then try
\xdef\mycmd{\expandonce\mycmd \expandonce\x}
I expect the result to be
\mycmd=\noexpand\cos \noexpand\tan
What's happening? What am I not understanding here?
I guess I should conclude that there's something going on inside the tabular environment that I haven't tapped yet with my examples. But I'm not really sure what that would be.
\xdef\x{\cos}doesn't break ifamsmathis not loaded; it dies otherwise. With\mycmd=<something>do you mean that\mycmdexpands to<something>? – egreg Oct 01 '13 at 08:42amsmath. I guess I should have written\mycmd-><something>. I'm not really sure if I meant expands. I was trying to represent my understand of how\exandoncewould operate on the contents of the macro\mycmd. – A.Ellett Oct 01 '13 at 13:07\edefto define\list@of@agenda@items. If I redefine my key toitems for the agenda/.store in=\list@of@agenda@items,everything works as expected and I can get rid of the\noexpands at the user level. – A.Ellett Oct 01 '13 at 13:35\parthat makes your macros fail is because some of them are non long; in particular\aeset, but even if you make it\long, you'll fail because\pgffor@normal@listisn't\long. Using\protected\def\aepar{\par}can solve the issue, because a\protectedmacro will not be expanded in an\edefor\xdef. – egreg Oct 01 '13 at 15:24\par. What's happening with\let\mytrial\relaxthat's causing an infinite loop, but\def\mytrial{\relax}doesn't? – A.Ellett Oct 01 '13 at 17:51