3

Currently I'm trying to create an environment with several different \item-like commands. I want the arguments of the different commands to be ordered by their type.

Basically the usage of

\begin{ordered}
  \fruit{Apple}
  \vegetable{Salad}
  \vegetable{Bell Pepper}
  \fruit{Strawberry}
\end{ordered}

should result in

Apple
Strawberry
Salad
Bell Pepper

With the following Code this can be done on a basic level

\newenvironment{ordered}{
  \newcommand{\fruits}{}
  \newcommand{\fruit}[1]{
    \begingroup\def\temp{\renewcommand{\fruits}}
    \expandafter\expandafter\expandafter\endgroup
    \expandafter\temp\expandafter{\fruits{##1\\}}}
  \newcommand{\vegetables}{}
  \newcommand{\vegetable}[1]{
    \begingroup\def\temp{\renewcommand{\vegetables}}
    \expandafter\expandafter\expandafter\endgroup
    \expandafter\temp\expandafter{\vegetables{##1\\}}}
}{
  \fruits
  \vegetables
}

However, If I want my ordered environment to open a tabular containing the fruits and vegetables I get problems:

\newenvironment{ordered}{
  ...
  \begin{tabular}{l}
}{
  \fruits
  \vegetables
  \end{tabular}
}

Results in ! Missing } inserted. <inserted text> } l.31 \end{ordered}

Is there any way to use \fruits and \vegetables inside the ordered environment inside tabular?

dustin
  • 18,617
  • 23
  • 99
  • 204
Marcel
  • 33

1 Answers1

4

You're including groups in your addition to \fruits and \vegetables. Instead, the \g@addto@macro<cs>{<stuff>} macro can help adding <stuff> to <cs> (it requires a \makeatletter...\makeatother pair):

enter image description here

\documentclass{article}

\makeatletter
\newcommand{\fruits}{}
\newcommand{\fruit}[1]{\g@addto@macro\fruits{#1\\}}
\newcommand{\vegetables}{}
\newcommand{\vegetable}[1]{\g@addto@macro\vegetables{#1\\}}
\makeatother
\newenvironment{ordered}{%
  \renewcommand{\fruits}{\relax}\renewcommand{\vegetables}{\relax}% Clear fruits/vegetables
  \tabular{l}
}{%
  \expandafter\ifx\fruits\relax\else\fruits\hline\fi% Print fruits
  \vegetables% Prints vegetables
  \endtabular
}
\begin{document}

\begin{ordered}
  \fruit{Apple}%
  \vegetable{Salad}%
  \vegetable{Bell Pepper}%
  \fruit{Strawberry}%
\end{ordered}

\begin{ordered}
  \vegetable{Salad}%
  \vegetable{Bell Pepper}%
\end{ordered}

\end{document}

I've also removed some spurious spaces that are introduced from line breaks. For more on this see What is the use of percent signs (%) at the end of lines?

Werner
  • 603,163
  • Thanks, just what I wanted. But now I have some kind of enhancement: what if I want to put an \hline between \fruits and \vegetables, but only if there is at least one fruit in \fruits? I tried to check for empty \fruits by using \IfStrEq{\fruits}{\empty{}}{}{\fruits\hline} instead of \fruits but this results in ! Argument of \@firstoftwo has an extra }. <inserted text> \par l.16 \end{ordered} – Marcel Aug 14 '13 at 15:24
  • @Marcel: I've updated my answer. It includes resetting \fruits and \vegetables to \relax, which is used for testing whether or not to insert an \hline. – Werner Aug 14 '13 at 16:10