1

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:

enter image description here

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

3

1 Answer 1

2

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}

enter image description here

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.