# A problem of counters, timing and etoolbox

I am attempting a format for recipes. For input, each step of the method is accompanied by the ingredients for that step. The output places all of the ingredients together, and all of the steps of the method together, in what is commonly termed the “standard” format. Numbers are attached to the method steps that match the numbers for the ingredients, enabling a convenient correspondence between the two. I have tried various incantations involving \xdef and \xappto but seem to be missing an important piece of the puzzle. There is this but it uses collect.sty and I don't know how to apply that here. Clarification: I don't mean to imply that I want to use collect.sty here, but that I don't know that solution applies to this problem.

\documentclass[]{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in,bottom=0.7in]{geometry}
\usepackage{fontspec,xparse,etoolbox}

\newcounter{stepnum}

%% |=====8><-----| %%

\begingroup
\lccode~=\^^M
\lowercase{%
\endgroup
\NewDocumentCommand{\ingrline}{u{ }u{ }u{~}}{% #1=measure; #2=unit; #3=ingr. name
\xappto{\ingrbody}{\noexpand\ing{#1}{#2}{#3}}~
}%
\def\methline#1~{% Line of method text
\xappto{\methbody}{\unexpanded{\mth{#1}}}~%
}%
}

%% |=====8><-----| %%

\NewDocumentCommand{\ing}{mmm}{% Format: #1=measure; #2=unit; #3=ingr. name
\textbf{\xstepnum}:\ \textit{#1-#2}\ \emph{\textbf{#3}}\par%
}

\NewDocumentCommand{\mth}{m}{% Format: Line of method text
\textbf{\xstepnum:\ }#1\par
}

\NewDocumentEnvironment{recipe}{s O{} m}{% *=?; #2=keyval; #3=title
\setcounter{stepnum}{0}%% stepnum attaches both to group of ingredients and each method step
\gdef\ingrbody{}%
\gdef\methbody{}%
}{%
%% output \ingrbody and \methbody
\ingrbody
\par
\methbody
}

\NewDocumentEnvironment{step}{}{%
\stepcounter{stepnum}
\xdef\xstepnum{\thestepnum}
%% Assemble ingredients
\begingroup %% write ingredients to \ingrbody
\offinterlineskip
\obeylines
\everypar={\ingrline}
}{%
\endgroup %% End method
}

\NewDocumentCommand{\method}{}{%
\endgroup %% end ingredients
\begingroup %% begin method write method to \methbody
\offinterlineskip
\obeylines
\everypar={\methline}
}

%% |=====8><-----| %%

\setmainfont{STIX Two Text}

\pagestyle{empty}

\begin{document}

\begin{recipe}{A test}
\begin{step}% 1
1 cup butter (should be 1:'')
½ cup sugar (should be 1:'')
\method
Beat butter and sugar together until fluffy. (should be 1:)
\end{step}
\begin{step}% 2
2 cups flour
1 tablespoon baking powder
\method
Add to the butter mixture and combine.
\end{step}
\end{recipe}

\end{document}


gives this output:

The final format will be very different. This is just an MWE.

• Counters are always global (count registers are local). Nov 20, 2021 at 16:01
• Somewhat related: tex.stackexchange.com/questions/301298/… Nov 20, 2021 at 16:05
• @JohnKormylo I think I was--at some level--aware of that, but I don't see how that applies to this problem... Nov 20, 2021 at 19:57

You globally assign to \xstepnum the value of the stepnum counter right after the environment step is called and after the counter has been increased. But the lines to be finally printed are put together (and the relvant macros expanded) only when the recipe environment is closed. At this time, however, \xstepnum holds the number of the last step. Therefore this number will be put in every entry or line.

Therefore, you need to pass the current step through the whole macro chain instead, up to the point where you put together the final lines, like this:

\documentclass[]{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in,bottom=0.7in]{geometry}
\usepackage{fontspec,xparse,etoolbox}

\newcounter{stepnum}

%% |=====8><-----| %%

\begingroup
\lccode~=\^^M
\lowercase{%
\endgroup
\NewDocumentCommand{\ingrline}{mu{ }u{ }u{~}}{% #1=stepnum; #2=measure; #3=unit; #4=ingr. name
\xappto{\ingrbody}{\ing{#1}{#2}{#3}{#4}}~
}%
\NewDocumentCommand{\methline}{mu{~}}{% #1=stepnum; #2 rest
\xappto{\methbody}{\mth{#1}{#2}}~%
}%
}

%% |=====8><-----| %%

\NewDocumentCommand{\ing}{mmmm}{% Format: #1=stepnum; #2=measure; #3=unit; #4=ingr. name
\textbf{#1}:\ \textit{#2~#3}\ \emph{\textbf{#4}}\par%
}

\NewDocumentCommand{\mth}{mm}{% Format: #1=stepnum, #2=Line of method text
\textbf{#1:\ }#2\par
}

\NewDocumentEnvironment{recipe}{s O{} m}{% *=?; #2=keyval; #3=title
\setcounter{stepnum}{0} %% stepnum attaches both to group of ingredients and each method step
\gdef\ingrbody{}%
\gdef\methbody{}%
}{%
%% output \ingrbody and \methbody
\ingrbody
\par
\methbody
}

\NewDocumentEnvironment{step}{}{%
\stepcounter{stepnum}
%% Assemble ingredients
\begingroup %% write ingredients to \ingrbody
\offinterlineskip
\obeylines
\everypar={\ingrline{\thestepnum}}
}{%
\endgroup %% End method
}

\NewDocumentCommand{\method}{}{%
\endgroup %% end ingredients
\begingroup %% begin method write method to \methbody
\offinterlineskip
\obeylines
\everypar={\methline{\thestepnum}}
}

%% |=====8><-----| %%

\setmainfont{STIX Two Text}

\pagestyle{empty}

\begin{document}

\begin{recipe}{A test}
\begin{step}% 1
1 cup butter (should be 1:'')
½ cup sugar (should be 1:'')
\method
Beat butter and sugar together until fluffy. (should be 1:)
\end{step}
\begin{step}% 2
2 cups flour
1 tablespoon baking powder
\method
Add to the butter mixture and combine.
\end{step}
\end{recipe}

\end{document}


PS: In the definition of \ing I changed \textit{#1-#2} to \textit{#1~#2} since I believe that this is what you actually meant.

• Ah. I could see what was happening, not how to fix it. Fiat lux! Nov 20, 2021 at 20:58