# Delimiting-a-macro-with-itself-chain

Reading this question and the answer of @Werner made me think about if it is possible to have chains of self-delimiting macros like \XX abc \XX def \XX xyz or lets say

\begin{someenv}
\XX abc
\XX def
\XX xyz
\end{someenv}


The original definition will obviously fail here - insufficent number fo \XXs. So, a first step towards an easy redefinition of \XX could be to say

\def\XX#1\XX{do sth with #1\\ \XX}


The problem now is to terminate this chain in an elegant way. A rather rude and not desiderable way is shown in the MWE below.

\documentclass{article}

\def\XX#1\XX{do sth with #1\\ \XX}

\newenvironment{someenv}{\center}{\endcenter}

\def\abc{def}

\begin{document}
\begin{someenv}
\XX xyz
\XX abc
\XX \abc
\let\XX\empty %this is the bad guy that needs to be busted
\end{someenv}
\end{document}

• So what's the question here?
– Werner
Nov 29, 2014 at 7:49
• @Werner, "The problem now is to terminate this chain in an elegant way." Nov 29, 2014 at 10:16
• You need to supply some ending constraint, otherwise there's no way to stop it. The ending constraint may be explicit, but mostly its implicit in the form of a environment end, like in your example. It's already elegant (in my opinion) as the user doesn't see it or have to worry about it.
– Werner
Nov 29, 2014 at 15:50

You can't really do it unless you grab the token list you need as an argument.

Here's a possibility using environ; usage of expl3 is not necessary, but it provides a good framework for doing the desired job later.

\documentclass{article}
\usepackage{environ,expl3}

\ExplSyntaxOn
\NewEnviron{collectitems}
{
% clear the sequence
\seq_clear:N \l_ruben_collected_items_seq
% process the body
\exp_last_unbraced:No \ruben_collect_item:nw \BODY \item \q_stop
% do something with the sequence
\seq_show:N \l_ruben_collected_items_seq
}
\seq_new:N \l_ruben_collected_items_seq
\cs_new_protected:Npn \ruben_collect_item:nw #1 \item #2 \q_stop
{
\seq_put_right:Nx \l_ruben_collected_items_seq { \tl_trim_spaces:n { #1 } }
\tl_if_empty:nF { #2 }
{
\ruben_collect_item:nw #2 \q_stop
}
}
\ExplSyntaxOff

\begin{document}

\begin{collectitems}
\item Apple
\item Banana
\item Cherry
\end{collectitems}

\begin{collectitems}
\end{collectitems}

\end{document}


The body is collected in \BODY, which is expanded before prepending \ruben_collect_item:nw and appending \item \q_stop. The function \ruben_collect_item:nw is executed at every \item, until \item is immediately followed by \q_stop. The items are put in a sequence; the first item in the sequence will contain whatever is before the first \item token and can be used to check whether an \item token is actually seen, as the example shows.

The output on the terminal is

The sequence \l_ruben_collected_items_seq contains the items (without outer braces):
>  {}
>  {Apple}
>  {Banana}
>  {Cherry}.

l.31 \end{collectitems}

?
The sequence \l_ruben_collected_items_seq contains the items (without outer braces):
>  {}.

l.34 \end{collectitems}


Of course you will do something more useful with the sequence.

A “translation” into classical commands for a description environment that adapts the left margin to the width of the widest label.

\documentclass{article}
\usepackage{environ,enumitem}

\newlength\rubenwidth
\NewEnviron{xdescription}{%
\expandafter\rubenprocess\BODY\item\rubenprocess
\begin{itemize}[labelwidth=\rubenwidth,leftmargin=\rubenwidth,align=left,font=\bfseries]
\BODY
\end{itemize}
}
\makeatletter
\def\rubenprocess#1#2\item#3\rubenprocess{% #1 is always \item
\ruben@item#2\ruben@item
\if\relax\detokenize{#3}\relax
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\rubenprocess\item#3\rubenprocess}%
}
\def\ruben@item[#1]#2\ruben@item{%
\settowidth\@tempdima{\bfseries#1}%
\ifdim\rubenwidth<\@tempdima\rubenwidth=\@tempdima\fi
}

\begin{document}

\begin{xdescription}
\item[Apple] a round fruit
\item[Banana] not so round fruit
\item[Strawberry] small fruit with some more words
to get the text into two lines; will we succeed?
\end{xdescription}

\end{document}


Many variations of the idea are possible.

• Is it :nw or :ww (or :w)? Nov 29, 2014 at 10:34
• I am still really bad with xpl3. If it isn't too time consuming, could you show in addition how your solution would work without using LaTeX3 stuff? Nov 29, 2014 at 18:57
• @Ruben It mostly depends on what you want to do with the items. Nov 29, 2014 at 18:58
• Sure! Suppose I want to measure them with \settowidth and store them in a token register. Nov 29, 2014 at 19:00
• @Ruben Dinner time. Stay tuned. Nov 29, 2014 at 19:01

Is something like this what you want?

\documentclass{article}
\newenvironment{someenv}{\par\centering}{\par}
\newenvironment{XX}{\endXX\bfseries\itshape Do sth with\ }{\mdseries\upshape\par}
\let\notXX\endXX
\def\abc{ABC}
\begin{document}
before
\begin{someenv}
\XX xyz
\XX abc
\XX \abc
\notXX not under \verb|\XX| control % USE \notXX TO FORCE BREAK FROM \XX CONTROL
\XX ending line
\end{someenv}
after
\end{document}


You can get fancy and make the "something" that \XX does vary with the iteration of \XX within the environment.

\documentclass{article}
\newcounter{instance}
\newenvironment{someenv}{\par\centering\setcounter{instance}{0}}{\par}
\newenvironment{XX}{\endXX\bfseries\itshape\stepcounter{instance}
Iteration \theinstance: Do sth with\ }
{\mdseries\upshape\par}
\let\notXX\endXX
\def\abc{ABC}
\begin{document}
before
\begin{someenv}
\XX xyz
\XX abc
\XX \abc
\notXX not under \verb|\XX| control % USE \notXX TO FORCE BREAK FROM \XX CONTROL
\XX ending line
\end{someenv}
after
\end{document}


• Yes! To answer your question. (The \notXX function is neat :) Now, I have to check if it is appliable to other cases. For instance, like the one I described in the comments of egregs answer. Nov 29, 2014 at 21:09

You can use the code from Macro parameter delimited by more than one delimiter. This code defines the \seplist macro. Its argument is the list of separators. The separators in your example are \XX or \end (with space before this). The definition of \XX looks like:

\def\XXa#1{... macro with normal #1 parameter\par\sepused}
\def\XX{\seplist{{ \XX}{ \end}}\XXa}

\begin{someenv}
\XX abc
\XX def
\XX xyz
\end{someenv}

• Altough it's a “inside link”, this site prefers to have self contained answers. So it would be better if you include the \seplist definition in this answer. Dec 1, 2014 at 21:50