我正在寻找一种方法来查看命令定义中的下一个命令。让我试着解释一下我的意思。
假设我有一个\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}
这里忽略空格是无关紧要的,因为 中没有空格\cmd \nofoobar
,但还有
\peek_meaning_remove_ignore_spaces:NF
当然,您可以使用NTF
和NT
形式分别指定真实和虚假情况下的不同操作,或者仅指定真实情况下的操作。