在命令定义中查看下一个命令

在命令定义中查看下一个命令

我正在寻找一种方法来查看命令定义中的下一个命令。让我试着解释一下我的意思。

假设我有一个\cmd打印某些内容的命令,比如福巴。现在我希望该命令仅在以下命令不打印 foobar 时才打印\nofoobar。即

\cmd followed by some text or another command such as \cmd\foo should print foobar

然而,

\cmd\nofoobar should not print foobar.

理想情况下,空格也应该被忽略。也就是说,

\cmd   \nofoobar should also not print foobar

我不知道这是否可行,但我猜想存在一些 tex 魔法可以实现该功能。任何帮助都将不胜感激。

以下是一个完整的例子。

\documentclass{article}

\newcommand{\cmd}{%
%If next command after cmd is \nofoobar print nothing, else print foobar
foobar}

\newcommand{\nofoobar}{%
}

\begin{document}

\cmd this should say foobar% prints foobar

\cmd\nofoobar this should not say foobar % does not print foobar

\cmd   \nofoobar ideally this should also not say foobar % that is, spaces should be ignored 

\end{document}

答案1

要提前查看的底层 TeX 原语是\futurelet但不会跳过空格,LaTeX 将其包装在空格跳过循环中,因为\@ifnextchar它会\ifx测试标记是否等于指定的标记,因此尽管它的名称暗示“char”测试,但它可用于测试任何标记。

对于特殊情况,\cmd不需要跳过空格,因为命令名后没有空格标记,但如果\cmd带了参数而需要查看之后的内容\cmd{x},那么这个\@futurelet版本就很有用了,因为它会跳过 之后的空格}

\documentclass{article}

\makeatletter
\newcommand{\cmd}{\@ifnextchar\nofoobar{\@gobble}{foobar}}
\makeatother

\newcommand{\nofoobar}{nofoobar}


\begin{document}

\cmd this should say foobar% prints foobar

\cmd\nofoobar this should not say foobar % does not print foobar

\cmd   \nofoobar ideally this should also not say foobar % that is, spaces should be ignored 

\end{document}

答案2

expl3有一个非常强大的机制来查看下一个标记;您可以选择删除下一个标记或忽略空格(或执行两个操作)。

在这种情况下,您可以使用该系列的功能\peek_meaning

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\cmd}{}
 {
  \peek_meaning_remove:NF \nofoobar {foobar}
 }
\quark_new:N \nofoobar
\ExplSyntaxOff

\begin{document}

\cmd (this should say foobar)% prints foobar

\cmd\hfill (this should say foobar)% prints foobar

\cmd\nofoobar (this should not say foobar) % does not print foobar

\cmd   \nofoobar (ideally this should also not say foobar) % that is, spaces should be ignored

\end{document}

enter image description here

这里忽略空格是无关紧要的,因为 中没有空格\cmd \nofoobar,但还有

\peek_meaning_remove_ignore_spaces:NF

当然,您可以使用NTFNT形式分别指定真实和虚假情况下的不同操作,或者仅指定真实情况下的操作。

相关内容