使用命令检测右括号

使用命令检测右括号

我想制作一个命令来检测文档中写入的下一个标记是否是右括号。

我最好的方法是使用\@ifnextchar命令。事实上,以下代码:

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

确实打印。但是当我尝试在文件中yes定义命令时,如下所示:\demo.sty

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

并拨打电话:

{\demo}

它打印no。我猜想这是因为 LaTeX 在返回文档之前检测到了“命令结束”标记。无论如何,我想知道发生这种情况的实际原因,以及我应该如何定义最后一个示例中的\demo打印命令。yes

编辑:

在空白文档中,它实际上打印的是“是”。这是我的最小工作示例,其中打印的是“否”:

\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}

编辑2:

我刚刚注意到,在我的项目中,检测\demo最后一个\wrapper就足够了。所以:

\wrapper{\demo.\demo}

应该先打印no,然后yes。现在我这样看,我确信肯定还有另一种方法可以更轻松地获取此信息。

答案1

如果您想要的只是\demo打印yes它是否是列表中的最后一项,那么这应该可行:

\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}

在此处输入图片描述

答案2

虽然 @egreg 已经回答了这个问题,但这里有一个解决方案表面上避免expl3:正如已经提到的egreg,由于xparse建立在,所以expl3实际上无法避免它。

如果您想要做的只是检测是否\demo已作为列表中的最后一项传递,那么这应该有效:

\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}

但是,我应该指出,这里的社区很可能不赞成这种方法,因为我将旧样式@符号与隐式expl3样式包混合在一起。不过,如果您仍然觉得需要知道如何在不亲自编写代码的情况下实现这一点expl3,那么上面的方法应该可以满足您的要求。

相关内容