因为我编写了自己的文档类(好吧,我尝试......),这个问题困扰了我数周,因为在很多情况下我都需要这样的东西。
有没有办法测试输入流中的下一个标记列表是否为命令\foo
?我没有在网上或文档中发现类似的东西(或者我没有认出它)expl3
。例如,我想实现这样的事情:
\DeclareDocumentCommand \test { } {%
\if_next_tl:NTF \emph { % This function doesn't exist!
% Do something if true
}{
% Do something if false
}
}
所以当我写
Bla \test Bla Bla
执行了错误的代码,当我写
Bla \test \emph{Bla} Bla
真正的代码被执行。
我知道有像这样的 LaTeX3 函数\peek_after:Nw
和\peek_charcode:NTF
像这样的 TeX 宏\@ifnextchar
,但我不明白在这种情况下如何使用它们。我认为最好使用 LaTeX3 功能。也许,我完全错了,这不是在 LaTeX 中解决问题的正确尝试。
此外foo
:是否有类似的方法来测试输入流中是否存在环境?
背景
这是一个简化的示例,我可以使用它:我有一个命令\exercise
,它排版类似于标题的内容,后面跟着垂直空间。如果“正常”文本跟在后面\exercise
,这看起来应该如此。但如果我在后面添加一个枚举\exercise
,垂直空间看起来太小了---虽然它是相同的。我不知道为什么,但可能是因为项目之间的空间(这都是关于感知和视觉校正)。这就是为什么我想在标题后面添加一个非常小的额外空间\exercise
,如果它后面跟着一个枚举。所以我想要实现的是类似“条件间距”的东西。这是一个例子:
代码
\documentclass{scrartcl}
\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lipsum}
\usepackage{xparse}
\usepackage{noindentafter}
\DeclareDocumentCommand \exercise { } {%
\vspace{\baselineskip}
\noindent\textsf{\bfseries\Large Exercise}
\vspace{0.5\baselineskip}
\NoIndentAfterThis
}
\begin{document}
\exercise
\lipsum[1]
\begin{enumerate}
\item One
\item Two
\item Three
\end{enumerate}
\lipsum[1]
\exercise
\begin{enumerate}
\item One
\item Two
\item Three
\end{enumerate}
\end{document}
文档
结果如下。我认为,第二个“Exercise”后面的空间有点太小了。因此,\exercise
如果后面跟着枚举,我想在后面添加一些空间。
答案1
答案最终是公正的,\addvspace
而不是\vspace
。
顺便说一下,在 expl3 中,\peek_after:Nw \somecommand
将下一个标记保存到之后\somecommand
,\l_peek_token
然后执行\somecomand
,这可能会对进行检查\l_peek_token
。
更好的方法是将 bee与\peek_meaning:NTF \emph { True } { False }
之后的下一个标记进行比较,如果是 则返回 true 。{ False }
\emph
\emph
答案2
有一个 TeX 原语可以满足您的要求,它被称为\futurelet
。让我引用一下TeXbook:
TeX 还允许构造
\futurelet\cs
〈token₁〉〈token₂〉,其效果如下\let\cs=〈token₂〉〈token₁〉〈token₂〉
。
这个原语不能完全实现确切地你想要的,首先它不知道什么是 LaTeX,更不用说环境了。尽管如此,这个原始的实现了基本的展望您需要实现一个谓词来测试输入流中接下来是否会有某个环境的机制。
为什么在 LaTeX 中做这样的事情是个坏主意
TeX(该程序,不是普通的 TeX 也不是 LaTeX)是一种排版语言具有强大的宏系统,而 LaTeX 则是一种标记语言程序基于 TeX 构建。我们可以说它\futurelet
并不真正属于 LaTeX 定义的语言,它仍然存在,因为它已被删除或隐藏,但这不是你期望使用的东西。如果你这样做,你就会明确地取消 LaTeX 的保修,可以这么说。
困难必然会前瞻机制
如果您想尝试\futurelet
,您需要非常小心地编写宏,否则它们会非常脆弱。此外,您一定要查看以下主题:
- 当 catcode 被分配给 token 时
- TeX 如何比较 token
\if
- TeX 如何比较 token catcode
\ifcat
- TeX 如何比较 token 序列
\ifx
笔记:实际上,\ifx
比较两个宏的替换文本,但其最重要的用例是比较两个作为\edef
标记寄存器的 -d 版本的宏。
热身挑战
如果您有兴趣学习使用,\futurelet
您可以接受以下三个挑战:
- 编写一个
\ignorepaces
查看输入语句的版本。 - 编写一个
\futuretoks\to#1\then#2
宏,将 给出的标记存储\futurelet
在标记寄存器中#1
,并将控制权交给#2
。 它能很好地处理空格和换行符吗? - 编写一个包,允许定义带有诸如
\hbox
和\hfill
do 之类的参数的宏。
如果你拿起 3,你可以将它与getoptk
中的包进行比较tex/plain/contrib/getoptk
。除了宏指南之外,我还写了一篇TuGboat 上的文章描述它们的实现方式。