In designing hook interfaces for my package. I found out that I have two methods of defining hooks:
\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}
Which method is better (in speed and others)?
Best Answer
Generic hooks (such as
cmd
hooks) are used in very specific places (cmd
hooks are used when a command is called) and should not be manually used elsewhere. Nothing stops you from doing so, but that may cause confusion. Generic hooks are treated differently, since their definition (they are defined implicitly when you do\AddToHook{some/generic/hook}
) to their usage (used automatically inside another command or environment), so you shouldn't use it as a normal hook.The second option is the correct one: You create a normal hook called
mypkg/something
, and use it normally with\UseHook
.Also, using
mypkg/somehook
is a bit faster than using a genericcmd
hook because the latter tries to patch a command at\begin{document}
, which takes some (negligible) time, so there is no reason to misuse a genericcmd
hook.CAVEAT
Generic
cmd
hooks exist for a reason, of course! Suppose you wrote a nice package for typesetting tables, and you have a command like this:(not really impressive, I know :) and you want to, say, provide a hook for adding a header to that impressive table. If a user just did
\AddToHook{cmd/MagicTable/before}{<header>}
, the contents would be put outside of the tabular environment, and obviously not work. You could then provide for such users:In this case, you would “make the generic hook normal”, and the hook system wouldn't try to patch the hook into
\MagicTable
because you already told it the hook exists (by doing\NewHook
).This example is a bit obvious because tabular material simply doesn't work outside of the tabular environment, but in other cases, the package author could fine-tune the position of the
cmd/.../before
andcmd/.../after
hooks after people have been using such hooks.But if you are providing new functionality that is not simply “run this bunch of code before that command”, the correct alternative is to use a normal hook name.