4

I want to write a wrapper macro for an itemize environment. I would like to use the enumitem package (though the MWE here doesn't use or need this package). The problem is the parameters that I'm passing to the itemize environment may themselves be encoded inside another macro.

So for the wrapper macro, I wanted to write something like

\expandafter\itemize\expandafter[\anothermacro]

to handle this. But I got very unexpected results.

For some reason, the following two styles to embedding an itemize environment in a wrapper macro don't work identically.

The first style just uses \begin{itemize} followed by content and then a closing \end{itemize}.

The second style used \itemize followed by content and then a closing \enditemize. But in the second style, I get nested environments. Not at what I'm expecting.

\documentclass{article}
\pagestyle{empty}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \l_ae_itemize_clist
%%--------------------------------------------------------------------------------
%% Style A                                                                        
\cs_new:Npn \_ae_itemize_a:nn #1#2 
  {
    \clist_set:Nn \l_ae_itemize_clist { #2 }
     \begin{itemize}
    \clist_map_inline:Nn \l_ae_itemize_clist
      { \item ##1 }
    \end{itemize}
  }

\NewDocumentCommand{\aefooda}{ O{}mm }
    { \par\textbf{#2:}
      \_ae_itemize_a:nn {#1}{#3}
    }
%%--------------------------------------------------------------------------------
%% Style B                                                                        
\cs_new:Npn \_ae_itemize_b:nn #1#2 
  {
    \clist_set:Nn \l_ae_itemize_clist { #2 }
     \itemize
    \clist_map_inline:Nn \l_ae_itemize_clist
      { \item ##1 }
    \enditemize
  }

\NewDocumentCommand{\aefoodb}{ O{}mm }
    { \par\textbf{#2:}
      \_ae_itemize_b:nn {#1}{#3}
    }

\ExplSyntaxOff
\begin{document}

\textbf{Style A} works fine:
\aefooda{first}{a,b,c}

\aefooda{second}{a,b,c}

\aefooda{third}{a,b,c}

%%--------------------------------------------------------------------------------
%% Changing from style A to style B                                               
%%--------------------------------------------------------------------------------

\textbf{Style B} doesn't work:
\aefoodb{first}{a,b,c}

\aefoodb{second}{a,b,c}

\aefoodb{third}{a,b,c}

\end{document}

enter image description here

UPDATE

I've also tried something like the following:

\edef\aeBeginItemize[#1]{\noexpand\begin{itemize}[#1]}
\cs_new:Npn \_ae_itemize_c:nn #1#2 
  {
    \clist_set:Nn \l_ae_itemize_clist { #2 }
    \aeBeginItemize[#1]
    \clist_map_inline:Nn \l_ae_itemize_clist
      { \item ##1 }
    \end{itemize}
  }

But when I try to use it, I get an error from the enumitem package: it seems that enumitem is not longer able to process the keys correctly.

  • not an authoritative answer, but if you look at the definition of \begin in latex.ltx you will see that it does lots more than just launch the command that has the same name as the environment. the side effects of that are no doubt why you see quite different behavior in the two situations. – barbara beeton Aug 16 '13 at 20:08
3

itemize needs to know the nesting level it is, so it increments (locally) a counter. Within \begin{itemize} and \end{itemize} there are \begingroup and \endgroup that keep that assignment local. You surely can emulate it by adding \group_begin: and \group_end: to your function; choose between style A or B, where I show also how you can expand the option list for itemize:

\documentclass{article}
\usepackage{enumitem}
\usepackage{xparse}
\pagestyle{empty}

\ExplSyntaxOn
\clist_new:N \l_ae_itemize_clist

%%--------------------------------------------------------------------------
%% Style A                                                                        
\cs_new:Npn \_ae_itemize_a:nn #1#2 
  {
   \clist_set:Nn \l_ae_itemize_clist { #2 }
   \use:x { \exp_not:n { \begin{itemize} } [\exp_not:o {#1}] }
   \clist_map_inline:Nn \l_ae_itemize_clist { \item ##1 }
   \end{itemize}
  }

\NewDocumentCommand{\aefooda}{ O{}mm }
    { \par\textbf{#2:}
      \_ae_itemize_a:nn {#1}{#3}
    }
%%--------------------------------------------------------------------------
%% Style B                                                                        
\cs_new:Npn \_ae_itemize_b:nn #1#2 
  {
   \group_begin:
   \clist_set:Nn \l_ae_itemize_clist { #2 }
   \use:x { \exp_not:N \itemize [ \exp_not:o { #1 } ] }
   \clist_map_inline:Nn \l_ae_itemize_clist { \item ##1 }
   \enditemize
   \group_end:
  }

\NewDocumentCommand{\aefoodb}{ O{}mm }
    { \par\textbf{#2:}
      \_ae_itemize_b:nn {#1}{#3}
    }

\ExplSyntaxOff
\begin{document}

\textbf{Style A} works fine:
\aefooda{first}{a,b,c}

\aefooda{second}{a,b,c}

\aefooda{third}{a,b,c}

%%--------------------------------------------------------------------------
%% Changing from style A to style B                                               
%%--------------------------------------------------------------------------

\textbf{Style B} works too:
\aefoodb{first}{a,b,c}

\aefoodb[label=+]{second}{a,b,c}

\newcommand{\test}{label=X,font=\textbf}
\aefoodb[\test]{third}{a,b,c}

\end{document}

enter image description here

  • I've updated my answer. In the update there is an example of something which, on the face of it, seems kindred to what you're doing. But it doesn't work. Where it seems to differ is where you use \exp_not:o. Why does that seem to make all the difference? – A.Ellett Aug 16 '13 at 20:38
  • @A.Ellett The main problem is that \aeBeginItemize doesn't fully expand #1 at call time: once the definition is made, it's unimportant whether a macro was defined with \def or \edef. – egreg Aug 16 '13 at 20:58
  • Thanks for pointing out that matter about \def and \edef. That clued me in to what was going wrong with my update. I really should have put that defining inside the definition of the macro \_ae_itemiz_c:nn and then define it as \edef\aeBeginItemize{\noexpand\begin{itemize}[#1]} – A.Ellett Aug 16 '13 at 21:22
  • 1
    @A.Ellett No; macros like \textbf in #1 would make this bomb out. There's no risk with \exp_not:o, because after one expansion the resulting token list is protected by \unexpanded. – egreg Aug 16 '13 at 21:32
  • Oops, Then I've got a lot of refactoring to do. I hadn't thought about that. I've been using that \edef trick for a while now. – A.Ellett Aug 16 '13 at 21:36

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.