Tex 对生成输出时发生的事件触发的扩展提供了强大的支持,通过适当地运行六个标记列表之一:
\everycr \everydisplay \everyhbox \everymath \everypar \everyvbox
它们在诸如 Latex 类之类的地方使用效果很好,但它们的用处远没有达到应有的程度,因为赋值\everyfoo={\t\o ks}
只会擦除当前值,这使得包和文档的作者很难使用它们。Emacs 的 Elisp 有一种广为人知的技术,用于注册和注销要在事件中运行的代码,即钩子。
LaTeX3 项目的expl3
库提供了对管理标记列表的支持,而 LuaTeX 则通过一组 Lua 回调增强了 TeX 的事件处理机制。这些是否是对事件驱动的 TeX 代码的适当支持的开始,就像钩子一样可用?这是这些项目开发人员的优先事项吗?
答案1
LuaTeX 不提供这些现成的钩子,但你可以自己制作。LuaLaTeX 的人做了这件事(谢谢!)。请参阅http://github.com/mpg/luatexbase(还有luatexbase-mcb.dtx
:)。
答案2
当然,如果 LaTeX3 为这种事情提供了钩子,那就太好了——不是直接使用原语,而是提供一个可靠的方式来使用这些标记寄存器的接口。
不幸的是,为了提供一种良好的访问方式而放弃当前的 LaTeX2e 机制\everypar
是不可能的,因为这样会破坏与大量当前软件包的向后兼容性。实验性的 LaTeX3 软件包就是galley
为了开始思考这些想法而编写的,但我们距离任何可用于一般用途的东西都还很远。
答案3
从 LaTeX3 的角度进行扩展,我想这是一个我希望提供与 LaTeX2e 不同的输入语法的地方。正如问题所指出的那样,当前实现使用 token 寄存器语法
\everyfoo{tokens}
它会覆盖原来的内容\everyfoo
,除非你
\everyfoo\expandafter{\the\everyfoo tokens}
这并不明显。因此,更好的方法应该是像当前\AtBeginDocument
这样的方法:
\AtEveryFoo{tokens}
这是可加的。这种方法的实现相当简单。
概念验证一段简短的概念代码可能是 LaTeX3 的一种方法。这里的想法是 TeX 原语仅由内核使用,并提供两个单独的钩子。首先,应用内核所需的设置,然后是程序员的设置,最后是用户的设置。在演示中,我只考虑了这个\everymath
概念。我为用户提供了一个界面,用于添加和清除列表,以及 LaTeX2e\everymath
界面的别名。(在纯 LaTeX3 方法中,我会放弃这个类似 TeX 的界面,或者至少将其标记为弃用。)
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\makeatletter
\tl_new:N \l_every_math_programmers_tl
\tl_new:N \l_every_math_users_tl
\toks_set:Nn \tex_everymath:D {
\check@mathfonts % LaTeX2e's requirement
\tl_use:N \l_every_math_programmers_tl
\tl_use:N \l_every_math_users_tl
}
\NewDocumentCommand \InsertForEvery { m +m } {
\tl_put_right:cn { l_every_ #1 _users_tl } {#2}
}
\NewDocumentCommand \ClearForEvery { m } {
\tl_clear:c { l_every_ #1 _users_tl }
}
\RenewDocumentCommand \everymath { +m } { \InsertForEvery { math } {#1} }
\ExplSyntaxOff
\begin{document}
\InsertForEvery{math}{\mathrm{Look!\,}}
\( y = mx + c \)
\ClearForEvery{math}
\( y = mx + c \)
\end{document}
我应该补充一点,真正的实现需要错误检查等等。