# Detect closing braces with a command

I want to make a command that detects if the next token written in the document is a closing brace.

My best approach is to use the \@ifnextchar command. In fact, the following code:

\makeatletter
{
\@ifnextchar{\egroup}{yes}{no}
}
\makeatother


Does print yes. But when i try to define a command \demo in a .sty file as:

\newcommand{\demo}
{
\@ifnextchar{\egroup}{yes}{no}
}


and make the call:

{\demo}


It prints no. I suppose that this happens because LaTeX detects a "end of command" token before returning to the document. Anyway, I would like to know the actual reason of why this happens, and how should I define the \demo command for printing yes in the last example.

edit:

In a blank document it actually prints yes. This is my minimal working example where it prints no:

\documentclass[a5paper]{book}

\usepackage{xparse}

\NewDocumentCommand{\wrapper}{ >{\SplitList{.}} m }
{
\begin{itemize}
\ProcessList{#1}{\entry}
\end{itemize}
}

\newcommand{\entry}[1]
{
\item \begin{math} #1 \end{math}
}
\makeatletter
\newcommand{\demo}{\@ifnextchar{\egroup}{yes}{no}}
\makeatother

\begin{document}

\wrapper{a.b.{\demo}.d} prints no
but {\demo} prints yes

\end{document}


edit 2:

I just noticed that in my project, detecting that \demo is the last one within a \wrapper could be enough. So:

\wrapper{\demo.\demo}


should print no first and then yes. Now that I look at it this way, I'm sure it has to be another way to get this information easier.

-
I get yes. Can you show a minimal example? – egreg Apr 26 '14 at 15:59
(a) Your real world macro \demo should not contain any code between \@ifnextchar with its three arguments and the end of the macro. Otherwise \@ifnextchar would just see the first token of the code. (b) \@ifnextchar gobbles following spaces (for example, the space in the definition by the line end). If spaces matter, then \ltx@ifnextchar@nospace of package ltxmcds can be used. – Heiko Oberdiek Apr 26 '14 at 16:06
The braces around \demo are stripped off by effect of \SplitList. – egreg Apr 26 '14 at 16:29
A much slower routine needs to be used if you don't want the braces are stripped off. Can you tell why you want to do this? – egreg Apr 26 '14 at 16:36
@A.Ellett That's a general TeX feature: when arguments are grabbed (delimited or undelimited) a pair of braces is stripped off unless, in the delimited case, they would leave unbalanced braces. – egreg Apr 26 '14 at 17:22

If all you want is that \demo prints yes if it's the last item in the list, then this should work:

\documentclass[a5paper]{book}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\wrapper}{ m }
{
\begin{itemize}
\azpillaga_wrapper:n { #1 }
\end{itemize}
}

\NewDocumentCommand{\demo}{ }
{
\azpillaga_demo:
}

\seq_new:N \l__azpillaga_input_seq
\tl_new:N \l__azpillaga_last_tl
\bool_new:N \l__azpillaga_last_item_bool
\cs_new_protected:Npn \azpillaga_wrapper:n #1
{
\bool_set_false:N \l__azpillaga_last_item_bool
\seq_set_split:Nnn \l__azpillaga_input_seq { . } { #1 }
\seq_pop_right:NN \l__azpillaga_input_seq \l__azpillaga_last_tl
\seq_map_inline:Nn \l__azpillaga_input_seq { \entry{##1} }
\bool_set_true:N \l__azpillaga_last_item_bool
\entry {\tl_use:N \l__azpillaga_last_tl }
}
\cs_new:Npn \azpillaga_demo:
{
\bool_if:NTF \l__azpillaga_last_item_bool
{
yes
}
{
no
}
}
\ExplSyntaxOff

\newcommand{\entry}[1]
{
\item \begin{math} #1 \end{math}
}

\begin{document}

Not at the end:
\wrapper{a.b.\demo.d}

At the end:
\wrapper{\demo.\demo}

\end{document}


-
This is definitively a working answer. It's important to keep my document free of expl3 syntax. Can someone build an alternative? – Martin Azpillaga Apr 26 '14 at 17:33
@MartinAzpillaga If you use xparse you have expl3 anyway. – egreg Apr 26 '14 at 17:35
At this moment, I know nothing about expl3. As I mentioned above, this code is part of a more complicated structure which I would be unable to switch to expl3 right now. If I can't get a non-expl3 answer, I'll probably post a new question with the whole structure so a full restructuring can be made. – Martin Azpillaga Apr 26 '14 at 17:52
Sorry, you can't do this with xparse only. – egreg Apr 26 '14 at 17:58
Then I think this is the best answer. Good job :) – Martin Azpillaga Apr 27 '14 at 12:16

Though this has already been answered by @egreg , here's a solution that superficially avoids expl3: as already mentioned by egreg, since xparse is built on expl3 there really is no avoiding it.

If all you want to do is to be able to detect whether \demo has been passed as the last item in a list, this should work:

\documentclass[a5paper]{book}
\usepackage{xparse}

\makeatletter

\def\mylastitem{\relax}

\NewDocumentCommand\wrapper{ m }
{\ae@wrapper{#1\mylastitem}}

\NewDocumentCommand{\ae@wrapper}{ >{\SplitList{.}} m }
{\begin{itemize}
\ProcessList{#1}{\entry}
\end{itemize}}

\newcommand{\entry}[1]{\item \begin{math} #1 \end{math}}

\newcommand\demo{\@ifnextchar\mylastitem{\textit{yes}}{\textit{no}}}

\makeatother

\begin{document}

\wrapper{acd.b.{\demo}.d} prints \textit{no}

\wrapper{acd.b.c.\demo} prints \textit{yes}

\end{document}


However, I should point out that the community here will most likely frown on this sort of approach since I'm mixing the older style @ notation with an implicit expl3 style package. Nevertheless, if you still feel the need to know how to get this to work without having to actually write expl3 code yourself, the above should do the trick for you.

-