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}. <recently read> } l.31 \end{collectitems} ? The sequence \l_ruben_collected_items_seq contains the items (without outer braces): > {}. <recently read> } 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.