在为我的包设计钩子接口时,我发现我有两种定义钩子的方法:
\documentclass{article}
\begin{document}
\section*{Method 1: Use Command Hooks}
\NewDocumentCommand\MyPkgSomeHook{}{}
\AddToHook{cmd/MyPkgSomeHook/before}{hello}
\AddToHook{cmd/MyPkgSomeHook/before}{world}
\UseHook{cmd/MyPkgSomeHook/before}
\section*{Method 2: Use Package Hooks}
\NewHook{mypkg/somehook}
\AddToHook{mypkg/somehook}{hello}
\AddToHook{mypkg/somehook}{world}
\UseHook{mypkg/somehook}
\end{document}
哪种方法更好(速度和其他方面)?
答案1
通用钩子(例如cmd
hooks)用于非常特定的地方(cmd
调用命令时使用钩子),不应在其他地方手动使用。没有什么可以阻止你这样做,但这可能会造成混淆。通用钩子的定义(当你这样做时它们是隐式定义的\AddToHook{some/generic/hook}
)与它们的用法(在另一个命令或环境中自动使用)不同,所以你不应该把它当作普通钩子来使用。
第二个选项是正确的:您创建一个名为的普通钩子mypkg/something
,并将其与一起正常使用\UseHook
。
此外,使用mypkg/somehook
比使用通用钩子要快一点,cmd
因为后者尝试修补命令\begin{document}
,这需要一些(可忽略的)时间,所以没有理由滥用通用cmd
钩子。
警告
cmd
当然,通用钩子的存在是有原因的!假设你写了一个用于排版表格的漂亮包,并且你有一个这样的命令:
\NewDocumentCommand \MagicTable { m m }
{
\begin{tabular}{rl}
#1 & #2 \\
\end{tabular}
}
(我知道这并不令人印象深刻 :) 并且您想要提供一个钩子来为该令人印象深刻的表格添加标题。如果用户刚刚这样做\AddToHook{cmd/MagicTable/before}{<header>}
,内容将放在表格环境之外,显然不起作用。然后您可以为此类用户提供:
\NewDocumentCommand \MagicTable { m m }
{
\begin{tabular}{rl}
\UseHook{cmd/MagicTable/before}
#1 & #2 \\
\end{tabular}
}
\NewHook{cmd/MagicTable/before}
在这种情况下,您可以“使通用钩子变得正常”,并且钩子系统不会尝试修补该钩子,\MagicTable
因为您已经告诉它该钩子存在(通过执行\NewHook
)。
这个例子有点明显,因为表格材料在表格环境之外根本不起作用,但在其他情况下,包作者可以在人们使用这样的钩子之后微调cmd/.../before
和钩子的位置。cmd/.../after
但是如果您提供的新功能不是简单的“在该命令之前运行这堆代码”,那么正确的替代方法是使用普通的钩子名称。