summaryrefslogtreecommitdiff
path: root/macros/latex-dev/base/lthooks.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex-dev/base/lthooks.dtx')
-rw-r--r--macros/latex-dev/base/lthooks.dtx1891
1 files changed, 1187 insertions, 704 deletions
diff --git a/macros/latex-dev/base/lthooks.dtx b/macros/latex-dev/base/lthooks.dtx
index 20e172a57f..3969a2be56 100644
--- a/macros/latex-dev/base/lthooks.dtx
+++ b/macros/latex-dev/base/lthooks.dtx
@@ -31,8 +31,8 @@
%%% From File: lthooks.dtx
%
% \begin{macrocode}
-\def\lthooksversion{v1.0n}
-\def\lthooksdate{2021/05/26}
+\def\lthooksversion{v1.0r}
+\def\lthooksdate{2021/09/06}
% \end{macrocode}
%
%<*driver>
@@ -47,7 +47,7 @@
\vbox_unpack_drop:N \l__codedoc_macro_box
\hbox { \llap { \__codedoc_print_macroname:nN {#1} #2
\MacroFont % <----- without it the \ is in lmr10 if a link is made
- \
+ \
} }
}
\int_incr:N \l__codedoc_macro_int
@@ -74,9 +74,9 @@
% \providecommand\pho[1]{\marginpar{\footnotesize PhO: #1}}
% \providecommand\phoinline[1]{\begin{quote}\itshape\footnotesize PhO: #1\end{quote}}
%
-%
%
-% \title{The \texttt{lthooks} package\thanks{This package has version
+%
+% \title{\LaTeX{}'s hook management\thanks{This module has version
% \lthooksversion\ dated \lthooksdate, \copyright\ \LaTeX\
% Project.}}
%
@@ -127,22 +127,18 @@
%
% \subsubsection{Declaring hooks}
%
-% With a few exceptions, hooks have to be declared before they can
-% be used. The exceptions are the generic hooks for commands,
-% environments (i.e., executed at \cs{begin} and \cs{end}) and
-% hooks run when loading files, e.g. before and after a package is
-% loaded, etc. Their hook names depend on the command,
-% environment or the
-% file name and so declaring them beforehand is not practical.
-%
+% With a few exceptions, hooks have to be declared before they can
+% be used. The exceptions are the generic hooks for commands and
+% environments (executed at \cs{begin} and \cs{end}), and the
+% hooks run when loading files (see section~\ref{sec:generic}).
%
% \begin{function}{\NewHook}
% \begin{syntax}
% \cs{NewHook} \Arg{hook}
% \end{syntax}
% Creates a new \meta{hook}.
-% If this is a hook provided as part of a package it is suggested
-% that the \meta{hook} name is always structured as follows:
+% If this hook is declared within a package it is suggested
+% that its name is always structured as follows:
% \meta{package-name}\texttt{/}\meta{hook-name}. If necessary you
% can further subdivide the name by adding more \texttt{/} parts.
% If a hook name is already taken, an error is raised and the hook
@@ -180,17 +176,19 @@
% \end{function}
%
%
-% \subsubsection{Special declarations for hooks}
+% \subsubsection{Special declarations for generic hooks}
%
% The declarations here should normally not be used. They are available
% to provide support for special use cases mainly involving
% generic command hooks.
%
-% \begin{function}{\DisableHook}
+% \changes{v1.0p}{2021/08/20}{Documentation updates for generic hook commands (gh/638)}
+%
+% \begin{function}{\DisableGenericHook}
% \begin{syntax}
-% \cs{DisableHook} \Arg{hook}
+% \cs{DisableGenericHook} \Arg{hook}
% \end{syntax}
-% After this declaration the \meta{hook} is no longer usable: Any
+% After this declaration\footnotemark{} the \meta{hook} is no longer usable: Any
% attempt to add further code to it will result in an error and any
% use, e.g., via \cs{UseHook}, will simply do nothing.
%
@@ -201,37 +199,27 @@
%
% The \meta{hook} can be specified using the dot-syntax to denote
% the current package name. See section~\ref{sec:default-label}.
-% \end{function}
+% \end{function}\footnotetext{In the 2020/06 release this command was
+% called \cs{DisableHook}, but that name was misleading as it
+% shouldn't be used to disable non-generic hooks.}
%
%
-% \begin{function}{\ProvideHook}
+% \begin{function}{\ActivateGenericHook}
% \begin{syntax}
-% \cs{ProvideHook} \Arg{hook}
+% \cs{ActivateGenericHook} \Arg{hook}
% \end{syntax}
-% Like \cs{NewHook} but does nothing if the hook was previously
-% declared with \cs{NewHook}. This declaration should only be used
-% in special situations, e.g., when command of another package
-% need to be altered and it is is not clear if for that command a
-% generic hook was already explicitly declared before.
-%
-% Normally \cs{NewHook} should be used instead.
+% This declaration activates a generic hook provided by a package/class
+% (e.g., one used in code with \cs{UseHook} or
+% \cs{UseOneTimeHook}) without it being explicitly declared with
+% \cs{NewHook}).
+% This command undoes the effect of \cs{DisableGenericHook}.
+% If the hook is already activated, this command does nothing.
+%
+% See section~\ref{sec:generic-hooks} for a discussion of when this
+% declaration is appropriate.
% \end{function}
%
-% \begin{function}{\ProvideReversedHook}
-% \begin{syntax}
-% \cs{ProvideReversedHook} \Arg{hook}
-% \end{syntax}
-% Like \cs{NewReversedHook} but does nothing if the hook was
-% previously declared as a reversed hook.
-% \end{function}
%
-% \begin{function}{\ProvideMirroredHookPair}
-% \begin{syntax}
-% \cs{ProvideMirroredHookPair} \Arg{hook-1} \Arg{hook-2}
-% \end{syntax}
-% A shorthand for
-% \cs{ProvideHook}\Arg{hook-1}\cs{ProvideReversedHook}\Arg{hook-2}.
-% \end{function}
%
%
%
@@ -272,12 +260,20 @@
% consumed and any further attempt to add to it will result in
% executing the code to be added immediately.
%
-% \fmiinline{Maybe add an error version as well?}
-%
% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
% A leading |.| is treated literally. See
% section~\ref{sec:default-label} for details.
-
+%
+% Using \cs{UseOneTimeHook} several times with the same
+% \Arg{hook} means that it only executes the first time it is used.
+% For example, if it is used in a command that can be called several times
+% then the hook executes during only the \emph{first} invocation of that
+% command; this allows its use as an \enquote{initialization hook}.
+%
+% Mixing \cs{UseHook} and \cs{UseOneTimeHook} for the same
+% \Arg{hook} should be avoided, but if this is done then neither will execute
+% after the first \cs{UseOneTimeHook}.
+%
% \end{function}
%
%
@@ -321,15 +317,19 @@
% When the optional argument \meta{label} is not provided, the
% \meta{default label} is used (see section~\ref{sec:default-label}).
%
-% If the code for that \meta{label} wasn't yet added to the
-% \meta{hook}, an order is set so that when some code attempts to add
-% that label, the removal order takes action and the code is not
-% added.
+% If there is no code under the \meta{label} in the \meta{hook},
+% or if the \meta{hook} does not exist, a warning is issued when
+% you attempt to \cs{RemoveFromHook}, and the command is ignored.
+% \cs{RemoveFromHook} should be used only when you know exactly what
+% labels are in a hook. Typically this will be when some code gets added to a hook
+% by a package, then later this code is removed by that same package.
+% If you want to prevent the execution of code from another
+% package, use the |voids| rule instead (see section~\ref{sec:rules}).
%
% If the optional \meta{label} argument is \texttt{*}, then all code chunks are
-% removed. This is rather dangerous as it drops code from other
-% packages one may not know about and should therefore not by used
-% by packages but only in document preambles!
+% removed. This is rather dangerous as it may well drop code from other
+% packages (that one may not know about); it should therefore not be used
+% in packages but only in document preambles!
%
% The \meta{hook} and \meta{label} can be specified using the
% dot-syntax to denote the current package name.
@@ -378,14 +378,28 @@
% The code is executed after the normal hook code has finished and
% it is executed only once, i.e. it is deleted after it was used.
%
-% Using the declaration is a global operation, i.e., the code is
-% not lost, even if the declaration is used inside a group and the
-% next invocation happens after the group. If the declaration is
+% Using this declaration is a global operation, i.e., the code is
+% not lost even if the declaration is used inside a group and the
+% next invocation of the hook happens after the end of that group.
+% If the declaration is
% used several times before the hook is executed then all code is
% executed in the order in which it was declared.\footnotemark
%
-% It is possible to nest declarations using the same hook (or
-% different hooks), e.g.,
+% If this declaration is used with a one-time hook then the code
+% is only ever used if the declaration comes before the hook’s
+% invocation. This is because, in contrast
+% to \cs{AddToHook}, the code in this declaration is not
+% executed immediately in the case when the invocation of the hook
+% has already happened---in other words, this code will truly execute
+% only on the next invocation of the hook (and in the case of a
+% one-time hook there is no such \enquote{next invocation}).
+% This gives you a choice: should my code execute
+% always, or should it execute only at the point where the
+% one-time hook is used (and not at all if this is impossible)? For
+% both of these possibilities there are use cases.
+%
+% It is possible to nest this declaration using the same hook (or
+% different hooks): e.g.,
% \begin{quote}
% \cs{AddToHookNext}\Arg{hook}\verb={=\meta{code-1}^^A
% \cs{AddToHookNext}\Arg{hook}\Arg{code-2}\verb=}=
@@ -404,6 +418,25 @@
% \end{function}\footnotetext{There is
% no mechanism to reorder such code chunks (or delete them).}
%
+%
+%
+% \begin{function}{\ClearHookNext}
+% \begin{syntax}
+% \cs{ClearHookNext}\Arg{hook}
+% \end{syntax}
+% Normally \cs{AddToHookNext} is only used when you know precisely
+% where it will apply and why you want some extra code at that
+% point. However, there are a few use cases in which such a
+% declaration needs to be canceled, for example, when
+% discarding a page with \cs{DiscardShipoutBox} (but even then not
+% always), and in such situations \cs{ClearHookNext} can be
+% used.
+% \end{function}
+%
+%
+%
+%
+%
% \subsubsection{Hook names and default labels}
% \label{sec:default-label}
%
@@ -424,7 +457,7 @@
%
% Except for \cs{UseHook}, \cs{UseOneTimeHook} and \cs{IfHookEmptyTF}
% (and their \pkg{expl3} interfaces \cs{hook_use:n},
-% \cs{hook_use_once:n} and \cs{hook_if_empty:nTF}, all \meta{hook}
+% \cs{hook_use_once:n} and \cs{hook_if_empty:nTF}), all \meta{hook}
% and \meta{label} arguments are processed in the same way: first,
% spaces are trimmed around the argument, then it is fully expanded
% until only character tokens remain. If the full expansion of the
@@ -458,7 +491,7 @@
% \AddToHook {./hook}[.]{code} % Same as \AddToHook{./hook}{code}
% \AddToHook {./hook}[./sub]{code}
% \DeclareHookRule{begindocument}{.}{before}{babel}
-% \AddToHook {file/after/foo.tex}{code}
+% \AddToHook {file/foo.tex/after}{code}
% \end{verbatim}
% are equivalent to:
% \begin{verbatim}
@@ -466,7 +499,7 @@
% \AddToHook {mypackage/hook}[mypackage]{code}
% \AddToHook {mypackage/hook}[mypackage/sub]{code}
% \DeclareHookRule{begindocument}{mypackage}{before}{babel}
-% \AddToHook {file/after/foo.tex}{code} % unchanged
+% \AddToHook {file/foo.tex/after}{code} % unchanged
% \end{verbatim}
%
% The \meta{default label} is automatically set equal to the name of the
@@ -534,7 +567,7 @@
% Packages that provide their own package-like interfaces
% (Ti\textit{k}Z's \cs{usetikzlibrary}, for example) can use
% \cs{PushDefaultHookLabel} and \cs{PopDefaultHookLabel} to set
-% dedicated labels and emulate \cs{usepackage}-like hook behaviour
+% dedicated labels and to emulate \cs{usepackage}-like hook behavior
% within those contexts.
%
% The |top-level| label is treated differently, and is reserved to the
@@ -588,6 +621,7 @@
% with that label from a package results in an error.
%
% \subsubsection{Defining relations between hook code}
+% \label{sec:rules}
%
% The default assumption is that code added to hooks by different
% packages are independent and the order in which they are executed is
@@ -712,8 +746,8 @@
% \item exist and be non-empty; and
% \item not exist (in which case emptiness doesn't apply);
% \end{itemize}
-% Hooks are a bit more complicated:
-% a hook may exist or not, and either way it may or may not be empty.
+% Hooks are a bit more complicated:
+% a hook may exist or not, and independently it may or may not be empty.
% This means that even a hook that doesn't exist may be non-empty and
% it can also be disabled.
%
@@ -854,7 +888,7 @@
% \end{quote}
% which means that the \meta{relation} applies to \meta{label-1} and
% \meta{label-2}, in that order, as detailed in \cs{DeclareHookRule}.
-% If the relation is \texttt{default} it means that that rule applies
+% If the relation is \texttt{default} it means that this rule applies
% to \meta{label-1} and \meta{label-2} in \emph{all} hooks, (unless
% overridden by a non-default relation).
%
@@ -905,9 +939,9 @@
%
%
%
-% \begin{function}{\hook_disable:n}
+% \begin{function}{\hook_disable_generic:n}
% \begin{syntax}
-% \cs{hook_disable:n} \Arg{hook}
+% \cs{hook_disable_generic:n} \Arg{hook}
% \end{syntax}
% Marks \Arg{hook} as disabled. Any further attempt to add code to
% it or declare it, will result in an error and any call to
@@ -921,34 +955,19 @@
% the current package name. See section~\ref{sec:default-label}.
% \end{function}
%
-% \begin{function}{\hook_provide:n}
+% \begin{function}{\hook_activate_generic:n}
% \begin{syntax}
-% \cs{hook_provide:n} \Arg{hook}
+% \cs{hook_activate_generic:n} \Arg{hook}
% \end{syntax}
% Like \cs{hook_new:n} but does nothing if the hook was previously
% declared with \cs{hook_new:n}. This declaration should only be used
% in special situations, e.g., when a command of another package
-% needs to be altered and it is is not clear if for that command a
+% needs to be altered and it is not clear if for that command a
% generic \hook{cmd} hook was already explicitly declared before.
%
% Normally \cs{hook_new:n} should be used instead.
% \end{function}
%
-% \begin{function}{\hook_provide_reversed:n}
-% \begin{syntax}
-% \cs{hook_provide_reversed:n} \Arg{hook}
-% \end{syntax}
-% Like \cs{hook_new_reversed:n} but does nothing if the hook was
-% previously declared as a reversed hook.
-% \end{function}
-%
-% \begin{function}{\hook_provide_pair:nn}
-% \begin{syntax}
-% \cs{hook_provide_pair:nn} \Arg{hook-1} \Arg{hook-2}
-% \end{syntax}
-% A shorthand for
-% \cs{hook_provide:n}\Arg{hook-1}\cs{hook_provide_reversed:n}\Arg{hook-2}.
-% \end{function}
%
%
%
@@ -1013,6 +1032,15 @@
% \end{function}
%
%
+% \begin{function}
+% {\hook_gclear_next_code:n}
+% \begin{syntax}
+% \cs{hook_gclear_next_code:n} \Arg{hook}
+% \end{syntax}
+% Undo any earlier \cs{hook_gput_next_code:nn}.
+% \end{function}
+%
+%
%
% \begin{function}{\hook_gremove_code:nn}
% \begin{syntax}
@@ -1020,10 +1048,9 @@
% \end{syntax}
% Removes any code for \meta{hook} labeled \meta{label}.
%
-% If the code for that \meta{label} wasn't yet added to the
-% \meta{hook}, an order is set so that when some code attempts to add
-% that label, the removal order takes action and the code is not
-% added.
+% If there is no code under the \meta{label} in the \meta{hook},
+% or if the \meta{hook} does not exist, a warning is issued when
+% you attempt to use \cs{hook_gremove_code:nn}, and the command is ignored.
%
% If the second argument is \texttt{*}, then all code chunks are
% removed. This is rather dangerous as it drops code from other
@@ -1138,7 +1165,7 @@
% which key-value pairs got added. However, that is only true if
% nothing other than adding happens!
%
-% Suppose, or example, you want to replace the code chunk for
+% Suppose, for example, you want to replace the code chunk for
% \texttt{packageA}, e.g.,
%\begin{verbatim}
% \RemoveFromHook{myhook}[packageA]
@@ -1297,7 +1324,7 @@
% \cs{AtBeginDocument} which is why it is supported.} (all three
% code chunks are executed one after another), but it makes little
% sense with a normal hook, because with a normal hook the first time
-% \verb=\UseHook{myhook}= is executed it would
+% \verb=\UseHook{myhook}= is executed it would
% \begin{itemize}
% \item
% execute \meta{code-1},
@@ -1315,6 +1342,70 @@
%
%
%
+% \subsection{Generic hooks provided by packages}
+% \label{sec:generic-hooks}
+%
+% \changes{v1.0p}{2021/08/20}{Section on generic hooks added (gh/638)}
+%
+% The hook management system also implements a category of hooks
+% that are called \enquote{Generic Hooks}. Normally a hook has to
+% be explicitly declared before it can be used in code. This
+% ensures that different packages are not using the same hook name
+% for unrelated purposes---something that would result in absolute
+% chaos. However, there are a number of \enquote{standard} hooks
+% where it is unreasonable to declare them beforehand, e.g, each
+% and every command has (in theory) an associated \texttt{before}
+% and \texttt{after} hook. In such cases, i.e., for command,
+% environment or file hooks, they can be used simply by adding code
+% to them with \cs{AddToHook}. For more specialized generic hooks,
+% e.g., those provided by \pkg{babel}, you have to additionally
+% enable them with \cs{ActivateGenericHook} as explained below.
+%
+% The generic hooks provided by \LaTeX{} are those for
+% \hook{cmd},
+% \hook{env},
+% \hook{file},
+% \hook{include}
+% \hook{package}, and
+% \hook{class},
+% and all these are available out of the box: you only have to
+% use \cs{AddToHook} to
+% add code to them, but you don't have to add \cs{UseHook} or
+% \cs{UseOneTimeHook} to your code, because this is already done for
+% you (or, in the case of \hook{cmd} hooks, the command’s code is
+% patched at \verb=\begin{document}=, if necessary).
+%
+% However, if you want to provide further generic hooks in your own
+% code, the situation is slightly different. To do this you should
+% use \cs{UseHook} or \cs{UseOneTimeHook}, but
+% \emph{without declaring the hook} with \cs{NewHook}. As
+% mentioned earlier, a call to \cs{UseHook} with an undeclared hook
+% name does nothing. So as an additional setup step, you need to
+% explicitly activate your generic hook. Note that a generic hook
+% produced in this way is always a normal hook.
+%
+% For a truly generic hook, with a variable part in the hook name,
+% such upfront activation would be difficult or impossible, because
+% you typically do not know what kind of variable parts may come up
+% in real documents.
+%
+% For example, \pkg{babel} may want to provide hooks such as
+% \hook{babel/afterextras/\meta{language}}. Language support in
+% \pkg{babel} is often done through external language
+% packages. Thus doing the activation for all languages inside the
+% core \pkg{babel} code is not a viable approach. Instead it needs
+% to be done by each language package (or by the user who wants to
+% use a particular hook).
+%
+% Because the hooks are not declared with \cs{NewHook} their names
+% should be carefully chosen to ensure that they are (likely to be)
+% unique. Best practice is to include the package or
+% command name, as was done in the \pkg{babel} example above.
+%
+% Generic hooks defined in this way are always normal hooks (i.e.,
+% you can't implement reversed hooks this way). This is a
+% deliberate limitation, because it speeds up the processessing
+% conciderably.
%
%
% \subsection{Private \LaTeX{} kernel hooks}
@@ -1354,8 +1445,8 @@
%
% \subsection{Legacy \LaTeXe{} interfaces}
%
-% \newcommand\onetimetext{%
-% This is a one-time hook, so after it is executed, all further
+% \newcommand\onetimetext{This is a one-time hook, so after it
+% is executed, all further
% attempts to add code to it will execute such code immediately
% (see section~\ref{sec:onetime-hooks}).}
%
@@ -1363,7 +1454,7 @@
% add to them. They are listed here and are retained for backwards
% compatibility.
%
-% With the new hook management several additional hooks have been added
+% With the new hook management, several additional hooks have been added
% to \LaTeX\ and more will follow. See the next section for what
% is already available.
%
@@ -1374,7 +1465,7 @@
% \end{syntax}
% If used without the optional argument \meta{label}, it works essentially
% like before, i.e., it is adding \meta{code} to the hook
-% \hook{begindocument}
+% \hook{begindocument}
% (which is executed inside \verb=\begin{document}=).
% However, all code added this way is labeled with the label
% \hook{top-level} (see section~\ref{sec:top-level})
@@ -1430,10 +1521,54 @@
% the processing.
%
%
-% \subsection{\LaTeXe{} commands and environments augmented by
-% hooks}
-%
-% \emph{intro to be written}
+% \section{\LaTeXe{} commands and environments augmented by hooks}
+%
+% In this section we describe the standard hooks that are now
+% offered by \LaTeX{}, or give pointers to other documents in which
+% they are described. This section will grow over time (and
+% perhaps eventually move to usrguide3).
+%
+% \subsection{Generic hooks}
+% \label{sec:generic}
+%
+% As stated earlier, with the exception of generic hooks, all hooks must
+% be declared with \cs{NewHook} before they can be used.
+% All generic hooks have names of the form
+% \enquote{\meta{type}/\meta{name}/\meta{position}}, where \meta{type}
+% is from the predefined list shown below, and \meta{name} is the variable
+% part whose meaning will depend on the \meta{type}. The last component,
+% \meta{position}, has more complex possibilities:
+% it can always be |before| or |after|; for |env| hooks, it can also be |begin|
+% or |end|; and for |include| hooks it can also be |end|. Each specific
+% hook is documented below, or in \texttt{ltcmdhooks-doc.pdf} or
+% \texttt{ltfilehook-doc.pdf}.
+%
+% The generic hooks provided by \LaTeX{} belong to one of the six types:
+% \begin{description}
+% \item[env] Hooks executed before and after environments --
+% \meta{name} is the name of the environment, and available values
+% for \meta{position} are |before|, |begin|, |end|, and |after|;
+% \item[cmd] Hooks added to and executed before and after commands --
+% \meta{name} is the name of the command, and available values
+% for \meta{position} are |before| and |after|;
+% \item[file] Hooks executed before and after reading a file --
+% \meta{name} is the name of the file (with extension), and
+% available values for \meta{position} are |before| and |after|;
+% \item[package] Hooks executed before and after loading packages --
+% \meta{name} is the name of the package, and available values for
+% \meta{position} are |before| and |after|;
+% \item[class] Hooks executed before and after loading classes --
+% \meta{name} is the name of the class, and available values for
+% \meta{position} are |before| and |after|;
+% \item[include] Hooks executed before and after \cs{include}d files --
+% \meta{name} is the name of the included file (without the |.tex|
+% extension), and available values for \meta{position} are |before|,
+% |end|, and |after|.
+% \end{description}
+%
+% Each of the hooks above are detailed in the following sections and
+% in linked documentation.
+% ^^A^^A^^A \pho{Wouldn't it be better to document all hooks here?}
%
% \subsubsection{Generic hooks for all environments}
%
@@ -1495,9 +1630,15 @@
% to add the outer hooks, etc.
%
%
+% Largely for compatibility with existing packages, the following
+% four commands are also available to set the environment hooks; but for
+% new packages we recommend directly using the hook names and
+% \cs{AddToHook}.
+%
+%
% \begin{function}{\BeforeBeginEnvironment}
% \begin{syntax}
-% \cs{BeforeBeginEnvironment} \oarg{label} \Arg{code}
+% \cs{BeforeBeginEnvironment} \oarg{label} \Arg{env} \Arg{code}
% \end{syntax}
% This declaration adds to the \hook{env/\meta{env}/before} hook
% using the \meta{label}. If \meta{label} is not given, the
@@ -1506,23 +1647,23 @@
%
% \begin{function}{\AtBeginEnvironment}
% \begin{syntax}
-% \cs{AtBeginEnvironment} \oarg{label} \Arg{code}
+% \cs{AtBeginEnvironment} \oarg{label} \Arg{env} \Arg{code}
% \end{syntax}
-% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/begin} hook.
+% This is like \cs{BeforeBeginEnvironment} but it adds to the \hook{env/\meta{env}/begin} hook.
% \end{function}
%
% \begin{function}{\AtEndEnvironment}
% \begin{syntax}
-% \cs{AtEndEnvironment} \oarg{label} \Arg{code}
+% \cs{AtEndEnvironment} \oarg{label} \Arg{env} \Arg{code}
% \end{syntax}
-% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/end} hook.
+% This is like \cs{BeforeBeginEnvironment} but it adds to the \hook{env/\meta{env}/end} hook.
% \end{function}
%
% \begin{function}{\AfterEndEnvironment}
% \begin{syntax}
-% \cs{AfterEndEnvironment} \oarg{label} \Arg{code}
+% \cs{AfterEndEnvironment} \oarg{label} \Arg{env} \Arg{code}
% \end{syntax}
-% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/after} hook.
+% This is like \cs{BeforeBeginEnvironment} but it adds to the \hook{env/\meta{env}/after} hook.
% \end{function}
%
%
@@ -1559,7 +1700,7 @@
%
%
%
-% \subsubsection{Hooks provided by \cs{begin}\texttt{\{document\}}}
+% \subsection{Hooks provided by \cs{begin}\texttt{\{document\}}}
% \label{sec:begindocument-hooks}
%
% Until 2020 \cs{begin}\texttt{\{document\}} offered exactly one
@@ -1618,7 +1759,7 @@
%
%
%
-% \subsubsection{Hooks provided by \cs{end}\texttt{\{document\}}}
+% \subsection{Hooks provided by \cs{end}\texttt{\{document\}}}
%
% \LaTeXe{} always provided \cs{AtEndDocument} to add code to the
% execution of \verb=\end{document}= just in front of the code that
@@ -1726,7 +1867,7 @@
%
%
%
-% \subsubsection{Hooks provided by \cs{shipout} operations}
+% \subsection{Hooks provided by \cs{shipout} operations}
% \label{sec:shipout}
%
% There are several hooks and mechanisms added to \LaTeX{}'s
@@ -1735,36 +1876,44 @@
% \texttt{ltshipout-code.pdf}.
%
%
+% \subsection{Hooks provided for paragraphs}
+% \label{sec:para}
+%
+% The paragraph processing has been augmented to include a number of
+% internal and public hooks. These are documented in
+% \texttt{ltpara-doc.pdf} or with code in
+% \texttt{ltpara-code.pdf}.
+%
+%
%
-% \subsubsection{Hooks provided in NFSS commands}
+% \subsection{Hooks provided in NFSS commands}
%
% In languages that need to support for more than one script in
-% parallel (and thus several sets of fonts), e.g., Latin and
-% Japanese fonts, NFSS font commands, such as \cs{sffamily}, need
+% parallel (and thus several sets of fonts, e.g., supporting both Latin and
+% Japanese fonts), NFSS font commands such as \cs{sffamily} need
% to switch both the Latin family to ``Sans Serif'' and in addition
% alter a second set of fonts.
%
-% To support this several NFSS have hooks in which such support can
-% be added.
+% To support this, several NFSS commands have hooks to which
+% such support can be added.
% \begin{description}
%
% \item[\hook{rmfamily}]
%
% After \cs{rmfamily} has done its initial checks and prepared a
-% any font series update this hook is executed and only
-% afterwards \cs{selectfont}.
+% font series update, this hook is executed before \cs{selectfont}.
%
% \item[\hook{sffamily}]
%
-% Like the \hook{rmfamily} hook but for the \cs{sffamily} command.
+% This is like the \hook{rmfamily} hook, but for the \cs{sffamily} command.
%
% \item[\hook{ttfamily}]
%
-% Like the \hook{rmfamily} hook but for the \cs{ttfamily} command.
+% This is like the \hook{rmfamily} hook, but for the \cs{ttfamily} command.
%
% \item[\hook{normalfont}]
%
-% The \cs{normalfont} command resets font encoding family series
+% The \cs{normalfont} command resets the font encoding, family, series
% and shape to their document defaults. It then executes this
% hook and finally calls \cs{selectfont}.
%
@@ -1779,21 +1928,36 @@
%
% \item[\hook{bfseries/defaults}, \hook{bfseries}]
%
-% If the \cs{bfdefault} was explicitly changed by the user its
+% If the \cs{bfdefault} was explicitly changed by the user, its
% new value is used to set the bf series defaults for the meta
-% families (rm/sf/tt) when \cs{bfseries} is called. In the
-% \hook{bfseries/defaults} hook further adjustments can be made
+% families (rm/sf/tt) when \cs{bfseries} is called. The
+% \hook{bfseries/defaults} hook allows further adjustments to be made
% in this case. This hook is only executed if such a change is
-% detected. In contrast the \hook{bfseries} hook is always
+% detected. In contrast, the \hook{bfseries} hook is always
% executed just before \cs{selectfont} is called to change to the
% new series.
%
%
% \item[\hook{mdseries/defaults}, \hook{mdseries}]
%
-% These two hooks are like the previous ones but used in
+% These two hooks are like the previous ones but they are in the
% \cs{mdseries} command.
%
+% \item[\hook{selectfont}]
+%
+% This hook is executed inside \cs{selectfont}, after the current
+% values for \textit{encoding}, \textit{family}, \textit{series},
+% \textit{shape}, and \textit{size} are evaluated and the new font
+% is selected (and if necessary loaded). After the hook has
+% executed, NFSS will still do any updates necessary for a new
+% \textit{size} (such as changing the size of \cs{strut}) and any
+% updates necessary to a change in \textit{encoding}.
+%
+% This hook is intended for use cases where, in parallel to a
+% change in the main font, some other fonts need to be altered
+% (e.g., in CJK processing where you may need to deal with several
+% different alphabets).
+%
% \end{description}
%
%
@@ -1859,7 +2023,7 @@
%
% \begin{macro}[EXP]{\@@_str_compare:nn}
% Private copy of \cs{__str_if_eq:nn}
-% \InternalDetectionOff
+% \InternalDetectionOff
% \begin{macrocode}
\cs_new_eq:NN \@@_str_compare:nn \__str_if_eq:nn
% \end{macrocode}
@@ -1892,13 +2056,6 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\g_@@_removal_list_prop}
-% A token list to hold delayed removals.
-% \begin{macrocode}
-\tl_new:N \g_@@_removal_list_tl
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}{\l_@@_cur_hook_tl}
% Stores the name of the hook currently being sorted.
% \begin{macrocode}
@@ -1916,13 +2073,6 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\g_@@_execute_immediately_prop}
-% List of hooks that from no on should not longer receive code.
-% \begin{macrocode}
-\prop_new:N \g_@@_execute_immediately_prop
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}{\g_@@_used_prop}
% All hooks that receive code (for use in debugging display).
% \begin{macrocode}
@@ -1963,6 +2113,13 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_clean_to_scan:w}
+% Removes tokens until the next \cs{s_@@_mark}.
+% \begin{macrocode}
+\cs_new:Npn \@@_clean_to_scan:w #1 \s_@@_mark { }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_tl_set:Nn,\@@_tl_set:Nx,
% \@@_tl_set:cn,\@@_tl_set:cx}
% Private copies of a few \pkg{expl3} functions. \pkg{l3debug} will
@@ -2055,7 +2212,7 @@
% \item[\cs{g_@@_\meta{hook}_code_prop}] A property list holding the code
% for the hook in separate chunks. The keys are by default the
% package names that add code to the hook, but it is possible
-% for packages to define other keys.
+% for packages to define other keys.
%
% \item[{\cs[no-index]{g_@@_\meta{hook}_rule_\meta{label1}\string|\meta{label2}_tl}}]
% A token list holding the relation between \meta{label1} and
@@ -2108,19 +2265,19 @@
% \label{sec:existence}
%
% A hook may be in different states of existence. Here we give an
-% overview of internal commands to set up hooks and explain how the
+% overview of the internal commands to set up hooks and explain how the
% different states are distinguished. The actual implementation
-% then follows in the next sections.
+% then follows in subsequent sections.
%
-% One problem we have to solve is, that we need to be able to add
+% One problem we have to solve is that we need to be able to add
% code to hooks (e.g., with \cs{AddToHook}) even if that code has
-% not been declared yet. For example, one package needs to write
-% into a hook of another package, but that package ay not get
-% loaded or only loaded later. Another problem most hooks require
-% declaration but this is not the case for the generic hooks.
+% not yet been declared. For example, one package needs to write
+% into a hook of another package, but that package may not get
+% loaded, or is loaded only later. Another problem is that most hooks,
+% but not the generic hooks, require a declaration.
%
-% We therefore distinguish the following states for a hook and they
-% are managed with four different tests: structure existence
+% We therefore distinguish the following states for a hook, which
+% are managed by four different tests: structure existence
% (\cs{@@_if_structure_exist:nTF}), creation
% (\cs{@@_if_usable:nTF}), declaration (\cs{@@_if_declared:nTF})
% and disabled or not (\cs{@@_if_disabled:nTF})
@@ -2151,12 +2308,12 @@
% \item [@@_if_disabled:nTF] returns |false|.
% \end{itemize}
%
-% The allowed acctions are the same as in the \enquote{not
+% The allowed actions are the same as in the \enquote{not
% existing} state.
%
% \item[declared]
%
-% A hook is in this state it is not disabled and was explicity declared (e.g.,
+% A hook is in this state it is not disabled and was explicitly declared (e.g.,
% with \cs{NewHook}). In this case the four tests give the
% following results:
% \begin{itemize}
@@ -2187,8 +2344,8 @@
%
% \item[disabled]
%
-% A hook in any state is moved to this state when
-% \cs{DisableHook} is used. This changes the tests to give the
+% A generic hook in any state is moved to this state when
+% \cs{DisableGenericHook} is used. This changes the tests to give the
% following results:
% \begin{itemize}
% \item [@@_if_structure_exist:nTF] \emph{unchanged}.
@@ -2197,7 +2354,7 @@
% \item [@@_if_disabled:nTF] returns |true|.
% \end{itemize}
% The structure test is unchanged (if the hook was unknown before it is
-% false, otherwise true). The usable test returns false so that
+% |false|, otherwise |true|). The usable test returns |false| so that
% any \cs{UseHook} will bypass the hook from now on. The
% declared test returns true so that any further \cs{NewHook}
% generates an error and the disabled test returns true so that
@@ -2240,8 +2397,8 @@
% \end{macrocode}
% \end{macro}
%
-%
-%
+%
+%
% \begin{macro}{\@@_make_usable:n}
%
% This initializes all hook data structures for the hook but if
@@ -2315,7 +2472,7 @@
% (\cs[no-index]{g_@@_\meta{hook}_code_prop}) and the |top-level|
% and |next| token lists. A hook is initialized with
% \cs{@@_init_structure:n} the first time anything is added to it.
-% Inizializing a hook just with \cs{@@_init_structure:n} will not
+% Initializing a hook just with \cs{@@_init_structure:n} will not
% make it usable with \cs{hook_use:n}.
% \begin{macrocode}
\cs_new_protected:Npn \@@_init_structure:n #1
@@ -2407,7 +2564,9 @@
%
% \subsubsection{Disabling and providing hooks}
%
-% \begin{macro}{\hook_disable:n}
+% \changes{v1.0p}{2021/08/20}{Renames of generic hook commands (gh/638)}
+%
+% \begin{macro}{\hook_disable_generic:n}
% \begin{macro}{\@@_disable:n}
% \begin{macro}[pTF]{\@@_if_disabled:n}
%
@@ -2423,11 +2582,11 @@
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2021/06/01}%
-%<latexrelease> {\hook_disable:n}{Disable~hooks}
+%<latexrelease> {\hook_disable_generic:n}{Disable~hooks}
% \end{macrocode}
-%
+%
% \begin{macrocode}
-\cs_new_protected:Npn \hook_disable:n #1
+\cs_new_protected:Npn \hook_disable_generic:n #1
{ \@@_normalize_hook_args:Nn \@@_disable:n {#1} }
\cs_new_protected:Npn \@@_disable:n #1
{
@@ -2447,9 +2606,9 @@
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/10/01}
-%<latexrelease> {\hook_disable:n}{Disable~hooks}
+%<latexrelease> {\hook_disable_generic:n}{Disable~hooks}
%<latexrelease>
-%<latexrelease>\cs_new_protected:Npn \hook_disable:n #1 {}
+%<latexrelease>\cs_new_protected:Npn \hook_disable_generic:n #1 {}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
@@ -2457,71 +2616,47 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\hook_provide:n}
-% \begin{macro}{\hook_provide_reversed:n}
-% \begin{macro}{\@@_provide:n}
-% The \cs{hook_provide:n} declaration declares a new hook if it
+% \begin{macro}{\hook_activate_generic:n}
+% \begin{macro}{\@@_activate_generic:n}
+% The \cs{hook_activate_generic:n} declaration declares a new hook if it
% wasn't declared already, in which case it only checks that the
% already existing hook is not a reversed hook.
-% The \cs{hook_provide_reversed:n} does the same for reversed hooks.
-% \hook{begindocument}.
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2021/06/01}%
-%<latexrelease> {\hook_provide:n}{Providing~hooks}
+%<latexrelease> {\hook_activate_generic:n}{Providing~hooks}
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \hook_provide:n #1
- { \@@_normalize_hook_args:Nn \@@_provide:nn {#1} { } }
-\cs_new_protected:Npn \hook_provide_reversed:n #1
- { \@@_normalize_hook_args:Nn \@@_provide:nn {#1} { - } }
+\cs_new_protected:Npn \hook_activate_generic:n #1
+ { \@@_normalize_hook_args:Nn \@@_activate_generic:nn {#1} { } }
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_provide:nn #1 #2
+\cs_new_protected:Npn \@@_activate_generic:nn #1 #2
{
% \end{macrocode}
-% If the hook to be provided was disabled we warn (for now --- this
+% If the hook to be activated was disabled we warn (for now --- this
% may change).
% \begin{macrocode}
\@@_if_disabled:nTF {#1}
- { \msg_warning:nnn { hooks } { provide-disabled } {#1} }
+ { \msg_warning:nnn { hooks } { activate-disabled } {#1} }
% \end{macrocode}
-% Otherwise we check if it was already declared.
+% Otherwise we check if the hook is not declared, and if it isn't,
+% figure out if it's reversed or not, then declare it accordingly.
% \begin{macrocode}
{
- \@@_if_declared:nTF {#1}
- {
-% \end{macrocode}
-% Issue an error if we try to provide a a hook that is reversed and
-% the already existing one is not (or vice versa).
-% \begin{macrocode}
- \str_if_eq:eeF { \tl_use:c { g_@@_#1_reversed_tl } } {#2}
- { \msg_error:nnn { hooks } { provide-error } {#1} }
- }
-% \end{macrocode}
-% If it wasn't declared, we declared as a normal or reversed hook
-% as appropriate.
-% \begin{macrocode}
+ \@@_if_declared:nF {#1}
{
\tl_new:c { g_@@_#1_declared_tl }
\@@_make_usable:n {#1}
- \tl_gset:cn { g_@@_#1_reversed_tl } {#2}
+ \tl_gset:cx { g_@@_#1_reversed_tl }
+ { \@@_if_generic_reversed:nT {#1} { - } }
}
}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\hook_provide_pair:nn}
-% A shorthand for providing a normal and a (matching) reversed hook in one go.
-% \begin{macrocode}
-\cs_new_protected:Npn \hook_provide_pair:nn #1#2
- { \hook_provide:n {#1} \hook_provide_reversed:n {#2} }
-% \end{macrocode}
-% \end{macro}
%
% \begin{macrocode}
%<latexrelease>\EndIncludeInRelease
@@ -2529,11 +2664,9 @@
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/10/01}
-%<latexrelease> {\hook_provide:n}{Providing~hooks}
+%<latexrelease> {\hook_activate_generic:n}{Providing~hooks}
%<latexrelease>
-%<latexrelease>\cs_new_protected:Npn \hook_provide_reversed:n #1 {}
-%<latexrelease>\cs_new_protected:Npn \hook_provide:n #1 {}
-%<latexrelease>\cs_new_protected:Npn \hook_provide_pair:nn #1#2 {}
+%<latexrelease>\cs_new_protected:Npn \hook_activate_generic:n #1 {}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
@@ -2600,8 +2733,8 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_currname_or_default:}
-% Uses \cs{g_@@_hook_curr_name_tl} if it is set, otherwise tries
-% \cs{@currname}. If neither is set, raises an error and uses the
+% This uses \cs{g_@@_hook_curr_name_tl} if it is set, otherwise it tries
+% \cs{@currname}. If neither is set, it raises an error and uses the
% fallback value \verb|label-missing|.
% \begin{macrocode}
\cs_new:Npn \@@_currname_or_default:
@@ -2610,7 +2743,7 @@
{
\tl_if_empty:NTF \@currname
{
- \msg_expandable_error:nnn { kernel } { should-not-happen }
+ \msg_expandable_error:nnn { latex2e } { should-not-happen }
{ Empty~default~label. }
\@@_make_name:n { label-missing }
}
@@ -2622,7 +2755,7 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_make_name:n,\@@_make_name:w}
-% Provides a standard sanitization of a hook's name.
+% This provides a standard sanitization of a hook's name.
% It uses \cs{cs:w} to build a control sequence out of the hook name,
% then uses \cs{cs_to_str:N} to get the string representation of that,
% without the escape character. \cs{cs:w}-based expansion is used
@@ -2646,7 +2779,7 @@
% \begin{macro}{\@@_normalize_hook_args:Nnn}
% \begin{macro}{\@@_normalize_hook_rule_args:Nnnnn}
% \begin{macro}{\@@_normalize_hook_args_aux:Nn}
-% Standard route for normalising hook and label arguments. The main
+% This is the standard route for normalizing hook and label arguments. The main
% macro does the entire operation within a group so that csnames made
% by \cs{@@_make_name:n} are wiped off before continuing. This means
% that this function cannot be used for \cs{hook_use:n}!
@@ -2689,16 +2822,151 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\@@_curr_name_push:n,\@@_curr_name_push_aux:n}
+% \begin{macro}{\@@_curr_name_pop:}
+% \begin{macro}{\@@_end_document_label_check:}
+% The token list \cs{g_@@_hook_curr_name_tl} stores the name of the
+% current package/file to be used as the default label in hooks.
+% Providing a consistent interface is tricky because packages can
+% be loaded within packages, and some packages may not use
+% \cs{SetDefaultHookLabel} to change the default label (in which
+% case \cs{@currname} is used).
+%
+% To pull that one off, we keep a stack that contains the default
+% label for each level of input. The bottom of the stack contains the
+% default label for the |top-level| (this stack should never go
+% empty). If we're building the format, set the default label to be
+% |top-level|:
+% \begin{macrocode}
+\tl_gset:Nn \g_@@_hook_curr_name_tl { top-level }
+% \end{macrocode}
+%
+% Then, in case we're in \pkg{latexrelease} we push something on
+% the stack to support roll forward. But in some rare cases,
+% \pkg{latexrelease} may be loaded inside another package (notably
+% \pkg{platexrelease}), so we'll first push the |top-level| entry:
+% \changes{v1.0i}{2021/03/18}
+% {Only add \texttt{top-level} if not already there.}
+% \begin{macrocode}
+%<latexrelease>\seq_if_empty:NT \g_@@_name_stack_seq
+%<latexrelease> { \seq_gput_right:Nn \g_@@_name_stack_seq { top-level } }
+% \end{macrocode}
+% then we dissect the \cs{@currnamestack}, adding \cs{@currname} to
+% the stack:
+% \changes{v1.0f}{2020/11/24}{Support for roll forward (gh/434)}
+% \begin{macrocode}
+%<latexrelease>\cs_set_protected:Npn \@@_tmp:w #1 #2 #3
+%<latexrelease> {
+%<latexrelease> \quark_if_recursion_tail_stop:n {#1}
+%<latexrelease> \seq_gput_right:Nn \g_@@_name_stack_seq {#1}
+%<latexrelease> \@@_tmp:w
+%<latexrelease> }
+%<latexrelease>\exp_after:wN \@@_tmp:w \@currnamestack
+%<latexrelease> \q_recursion_tail \q_recursion_tail
+%<latexrelease> \q_recursion_tail \q_recursion_stop
+% \end{macrocode}
+% and finally set the default label to be the \cs{@currname}:
+% \changes{v1.0i}{2021/03/18}
+% {Remove the (empty) \enquote{top-level} from \cs{@currnamestack}.}
+% \begin{macrocode}
+%<latexrelease>\tl_gset:Nx \g_@@_hook_curr_name_tl { \@currname }
+%<latexrelease>\seq_gpop_right:NN \g_@@_name_stack_seq \l_@@_tmpa_tl
+% \end{macrocode}
+%
+% Two commands keep track of the stack: when a file is input,
+% \cs{@@_curr_name_push:n} pushes the current default label onto the
+% stack and sets the new default label (all in one go):
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_curr_name_push:n #1
+ { \exp_args:Nx \@@_curr_name_push_aux:n { \@@_make_name:n {#1} } }
+\cs_new_protected:Npn \@@_curr_name_push_aux:n #1
+ {
+ \tl_if_blank:nTF {#1}
+ { \msg_error:nn { hooks } { no-default-label } }
+ {
+ \str_if_eq:nnTF {#1} { top-level }
+ {
+ \msg_error:nnnnn { hooks } { set-top-level }
+ { to } { PushDefaultHookLabel } {#1}
+ }
+ {
+ \seq_gpush:NV \g_@@_name_stack_seq \g_@@_hook_curr_name_tl
+ \tl_gset:Nn \g_@@_hook_curr_name_tl {#1}
+ }
+ }
+ }
+% \end{macrocode}
+% and when an input is over, the topmost item of the stack is popped,
+% since that label will not be used again, and \cs{g_@@_hook_curr_name_tl}
+% is updated to equal the now topmost item of the stack:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_curr_name_pop:
+ {
+ \seq_gpop:NNTF \g_@@_name_stack_seq \l_@@_return_tl
+ { \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl }
+ { \msg_error:nn { hooks } { extra-pop-label } }
+ }
+% \end{macrocode}
+%
+% At the end of the document we want to check if there was no
+% \cs{@@_curr_name_push:n} without a matching \cs{@@_curr_name_pop:}
+% (not a critical error, but it might indicate that something else is
+% not quite right):
+% \begin{macrocode}
+\tl_gput_right:Nn \@kernel@after@enddocument@afterlastpage
+ { \@@_end_document_label_check: }
+\cs_new_protected:Npn \@@_end_document_label_check:
+ {
+ \seq_gpop:NNT \g_@@_name_stack_seq \l_@@_return_tl
+ {
+ \msg_error:nnx { hooks } { missing-pop-label }
+ { \g_@@_hook_curr_name_tl }
+ \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl
+ \@@_end_document_label_check:
+ }
+ }
+% \end{macrocode}
+%
+% The token list \cs{g_@@_hook_curr_name_tl} is but a mirror of the
+% top of the stack.
%
+% \begin{macro}{\@@_set_default_hook_label:n,\@@_set_default_label:n}
+% Now define a wrapper that replaces the top of the stack with the
+% argument, and updates \cs{g_@@_hook_curr_name_tl} accordingly.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_set_default_hook_label:n #1
+ {
+ \seq_if_empty:NTF \g_@@_name_stack_seq
+ {
+ \msg_error:nnnnn { hooks } { set-top-level }
+ { for } { SetDefaultHookLabel } {#1}
+ }
+ { \exp_args:Nx \@@_set_default_label:n { \@@_make_name:n {#1} } }
+ }
+\cs_new_protected:Npn \@@_set_default_label:n #1
+ {
+ \str_if_eq:nnTF {#1} { top-level }
+ {
+ \msg_error:nnnnn { hooks } { set-top-level }
+ { to } { SetDefaultHookLabel } {#1}
+ }
+ { \tl_gset:Nn \g_@@_hook_curr_name_tl {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \subsection{Adding or removing hook code}
%
% \begin{macro}{\hook_gput_code:nnn}
-% \begin{macro}{\@@_gput_code:nnn,\@@_gput_code:nxv,\@@_hook_gput_code_do:nnn}
+% \begin{macro}{\@@_gput_code:nnn,\@@_hook_gput_code_do:nnn}
%
% With \cs{hook_gput_code:nnn}\Arg{hook}\Arg{label}\Arg{code} a
% chunk of \meta{code} is added to an existing \meta{hook} labeled
% with \meta{label}.
+% \changes{v1.0o}{2021/07/22}{Do not queue removals (gh/625)}
% \begin{macrocode}
\cs_new_protected:Npn \hook_gput_code:nnn #1 #2
{ \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} }
@@ -2708,61 +2976,46 @@
\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3
{
% \end{macrocode}
-% First check if the hook was used as a one-time hook:
+% First check if the code should be executed immediately, rather than
+% stored:
+% \changes{v1.0r}{2021/09/06}{Use dedicated conditional (gh/606)}
% \begin{macrocode}
- \prop_if_in:NnTF \g_@@_execute_immediately_prop {#1}
+ \@@_if_execute_immediately:nTF {#1}
{#3}
{
% \end{macrocode}
-% Then check if the current \meta{hook}/\meta{label} pair was marked
-% for removal, in which case \cs{@@_unmark_removal:nn} is used to
-% remove that mark (once). This may happen when a package removes
-% code from another package which was not yet loaded: the removal
-% order is stored, and at this stage it is executed by not adding to
-% the hook.
-% \begin{macrocode}
- \@@_if_marked_removal:nnTF {#1} {#2}
- { \@@_unmark_removal:nn {#1} {#2} }
- {
-% \end{macrocode}
-% If no removal is queued, we are free to add. Start by checking if
-% the hook exists.
+% Then check if the hook is usable.
% \begin{macrocode}
- \@@_if_usable:nTF {#1}
+ \@@_if_usable:nTF {#1}
% \end{macrocode}
% If so we simply add (or append) the new code to the property list
% holding different chunks for the hook. At \verb=\begin{document}=
% this is then sorted into a token list for fast execution.
% \begin{macrocode}
- {
- \@@_hook_gput_code_do:nnn {#1} {#2} {#3}
+ {
+ \@@_hook_gput_code_do:nnn {#1} {#2} {#3}
% \end{macrocode}
% However, if there is an update within the document we need to alter
% this execution code which is done by
% \cs{@@_update_hook_code:n}. In the preamble this does nothing.
% \begin{macrocode}
- \@@_update_hook_code:n {#1}
- }
+ \@@_update_hook_code:n {#1}
+ }
% \end{macrocode}
%
-% If the hook does not exist, however, before giving up try to
-% declare it as a generic hook, if its name matches one of the valid
-% patterns.
+% If the hook is not usable, before giving up, check if it's not
+% disabled and otherwise try to declare it as a generic hook, if its
+% name matches one of the valid patterns.
% \begin{macrocode}
- {
- \@@_if_disabled:nTF {#1}
- { \msg_error:nnn { hooks } { hook-disabled } {#1} }
- { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
- }
+ {
+ \@@_if_disabled:nTF {#1}
+ { \msg_error:nnn { hooks } { hook-disabled } {#1} }
+ { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
}
}
}
% \end{macrocode}
%
-% \begin{macrocode}
-\cs_generate_variant:Nn \@@_gput_code:nnn { nxv }
-% \end{macrocode}
-%
% This macro will unconditionally add a chunk of code to the given hook.
% \begin{macrocode}
\cs_new_protected:Npn \@@_hook_gput_code_do:nnn #1 #2 #3
@@ -2839,21 +3092,40 @@
% next-execution hooks does the same: it defers the code to
% \cs{hook_gput_next_code:nn} if the generic hook was declared, or
% to \cs{@@_gput_next_do:nn} otherwise.
+% \changes{v1.0p}{2021/08/25}{Standardise generic hook names (gh/648)}
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:nnn}
+%<latexrelease> {Standardise~generic~hook~names}
\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1
{
- \@@_try_declaring_generic_hook:nNNnn {#1}
- \hook_gput_code:nnn \@@_gput_undeclared_hook:nnn
+ \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+ \hook_gput_code:nnn
+ \@@_gput_undeclared_hook:nnn
+ {#1}
}
\cs_new_protected:Npn \@@_try_declaring_generic_next_hook:nn #1
{
- \@@_try_declaring_generic_hook:nNNnn {#1}
- \hook_gput_next_code:nn \@@_gput_next_do:nn
+ \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+ \hook_gput_next_code:nn
+ \@@_gput_next_do:nn
+ {#1}
}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:nnn}
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1
+%<latexrelease> {
+%<latexrelease> \@@_try_declaring_generic_hook:nNNnn {#1}
+%<latexrelease> \hook_gput_code:nnn \@@_gput_undeclared_hook:nnn
+%<latexrelease> }
+%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_next_hook:nn #1
+%<latexrelease> {
+%<latexrelease> \@@_try_declaring_generic_hook:nNNnn {#1}
+%<latexrelease> \hook_gput_next_code:nn \@@_gput_next_do:nn
+%<latexrelease> }
% \end{macrocode}
% \end{macro}
%
-%
% \begin{macro}{\@@_try_declaring_generic_hook:nNNnn,
% \@@_try_declaring_generic_hook_split:nNNnn}
%
@@ -2867,43 +3139,39 @@
% the function returns \meta{true} for a generic hook and \meta{false}
% in other cases.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_try_declaring_generic_hook:nNNnn #1
- {
- \@@_if_file_hook:wTF #1 / / \s_@@_mark
- {
- \exp_args:Ne \@@_try_declaring_generic_hook_split:nNNnn
- { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
- }
- { \@@_try_declaring_generic_hook_split:nNNnn {#1} }
- }
+%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook:nNNnn #1
+%<latexrelease> {
+%<latexrelease> \@@_if_file_hook:wTF #1 / \s_@@_mark {#1}
+%<latexrelease> {
+%<latexrelease> \exp_args:Ne \@@_try_declaring_generic_hook_split:nNNnn
+%<latexrelease> { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
+%<latexrelease> }
+%<latexrelease> { \@@_try_declaring_generic_hook_split:nNNnn {#1} }
+%<latexrelease> }
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_try_declaring_generic_hook_split:nNNnn #1 #2 #3
- {
- \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
- { #2 }
- { #3 } {#1}
- }
+%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook_split:nNNnn #1 #2 #3
+%<latexrelease> {
+%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+%<latexrelease> { #2 }
+%<latexrelease> { #3 } {#1}
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
-%
% \begin{macro}[TF]{\@@_try_declaring_generic_hook:wn}
-%
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2021/06/01}%
-%<latexrelease> {\@@_try_declaring_generic_hook:wn}{Support~cmd~hooks}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:wn}%
+%<latexrelease> {Standardise~generic~hook~names}
\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
#1 / #2 / #3 / #4 \scan_stop: #5 { TF }
{
- \tl_if_empty:nTF {#2}
- { \prg_return_false: }
+ \@@_if_generic:nTF {#5}
{
- \prop_if_in:NnTF \c_@@_generics_prop {#1}
+ \@@_if_usable:nF {#5}
{
- \@@_if_usable:nF {#5}
- {
% \end{macrocode}
% If the hook doesn't exist yet we check if it is a \texttt{cmd}
% hook and if so we attempt patching the command in addition to
@@ -2913,8 +3181,8 @@
% \cs{@@_patch_cmd_or_delay:Nnn} (defined in \texttt{ltcmdhooks})
% will generate an appropriate error message.
% \begin{macrocode}
- \str_if_eq:nnT {#1} { cmd }
- { \@@_try_put_cmd_hook:n {#5} }
+ \str_if_eq:nnT {#1} { cmd }
+ { \@@_try_put_cmd_hook:n {#5} }
% \end{macrocode}
%
% Declare the hook always even if it can't really be used (error
@@ -2923,26 +3191,125 @@
% Here we use \cs{@@_make_usable:n}, so that a \cs{hook_new:n} is still
% possible later.
% \begin{macrocode}
- \@@_make_usable:n {#5}
- }
- \prop_if_in:NnTF \c_@@_generics_reversed_ii_prop {#2}
- { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
- {
- \prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
- { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
- }
- \prg_return_true:
+ \@@_make_usable:n {#5}
+ }
+ \@@_if_generic_reversed:nT {#5}
+ { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+ \prg_return_true:
+ }
+ {
+% \end{macrocode}
+%
+% Generic hooks are all named \meta{type}/\meta{name}/\meta{place},
+% where \meta{type} and \meta{place} are predefined
+% (\cs{c_@@_generic_\meta{type}/./\meta{place}_tl}), and \meta{name}
+% is the variable component. Older releases had some hooks with the
+% \meta{name} in the third part, so the code below supports that
+% syntax for a while, with a warning.
+%
+% The \cs{exp_after:wN} |...| \cs{exp:w} trick is there to remove the
+% conditional structure inserted by
+% \cs{@@_try_declaring_generic_hook:wnTF} and thus allow access to the
+% tokens that follow it, as is needed to keep things going.
+%
+% When the deprecation cycle ends, the lines below should all be
+% replaced by \cs{prg_return_false:}.
+% \begin{macrocode}
+ \@@_if_deprecated_generic:nTF {#5}
+ {
+ \@@_deprecated_generic_warn:n {#5}
+ \exp_after:wN \@@_declare_deprecated_generic:NNn
+ \exp:w % \exp_end:
}
{ \prg_return_false: }
}
}
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_deprecated_generic_warn:Nn,
+% \@@_deprecated_generic_warn:Nw,
+% }
+% \cs{@@_deprecated_generic_warn:n} will issue a deprecation warning
+% for a given hook, and mark that hook such that the warning will not
+% be issued again (multiple warnings can be issued, but only once per
+% hook).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_deprecated_generic_warn:n #1
+ { \@@_deprecated_generic_warn:w #1 \s_@@_mark }
+\cs_new_protected:Npn \@@_deprecated_generic_warn:w
+ #1 / #2 / #3 \s_@@_mark
+ {
+ \if_cs_exist:w @@~#1/#2/#3 \cs_end: \else:
+ \msg_warning:nnnnn { hooks } { generic-deprecated } {#1} {#2} {#3}
+ \fi:
+ \cs_gset_eq:cN { @@~#1/#2/#3 } \scan_stop:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_do_deprecated_generic:Nn,
+% \@@_do_deprecated_generic:Nw,
+% \@@_declare_deprecated_generic:NNw,
+% \@@_declare_deprecated_generic:NNw,
+% }
+% Now that the user has been told about the deprecation, we proceed by
+% swapping \meta{name} and \meta{place} and adding the code to the
+% correct hook.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_do_deprecated_generic:Nn #1 #2
+ { \@@_do_deprecated_generic:Nw #1 #2 \s_@@_mark }
+\cs_new_protected:Npn \@@_do_deprecated_generic:Nw #1
+ #2 / #3 / #4 \s_@@_mark
+ { #1 { #2 / #4 / #3 } }
+\cs_new_protected:Npn \@@_declare_deprecated_generic:NNn #1 #2 #3
+ { \@@_declare_deprecated_generic:NNw #1 #2 #3 \s_@@_mark }
+\cs_new_protected:Npn \@@_declare_deprecated_generic:NNw #1 #2
+ #3 / #4 / #5 \s_@@_mark
+ {
+ \@@_try_declaring_generic_hook:wnTF #3 / #5 / #4 / \scan_stop:
+ { #3 / #5 / #4 }
+ #1 #2 { #3 / #5 / #4 }
+ }
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
+% \end{macro}
%
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\@@_try_declaring_generic_hook:wn}{Support~cmd~hooks}
-%<latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_try_declaring_generic_hook:wn}
+%<latexrelease> {Support~cmd~hooks}
+%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
+%<latexrelease> {
+%<latexrelease> \tl_if_empty:nTF {#2}
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> {
+%<latexrelease> \prop_if_in:NnTF \c_@@_generics_prop {#1}
+%<latexrelease> {
+%<latexrelease> \@@_if_usable:nF {#5}
+%<latexrelease> {
+%<latexrelease> \str_if_eq:nnT {#1} { cmd }
+%<latexrelease> { \@@_try_put_cmd_hook:n {#5} }
+%<latexrelease> \@@_make_usable:n {#5}
+%<latexrelease> }
+%<latexrelease> \prop_if_in:NnTF \c_@@_generics_reversed_ii_prop {#2}
+%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+%<latexrelease> {
+%<latexrelease> \prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
+%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+%<latexrelease> }
+%<latexrelease> \prg_return_true:
+%<latexrelease> }
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> }
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:wn}%
+%<latexrelease> {Support~cmd~hooks}
%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
%<latexrelease> {
@@ -2968,77 +3335,107 @@
% \end{macrocode}
% \end{macro}
%
+%
% \begin{macro}[pTF]{\@@_if_file_hook:w}
% \cs{@@_if_file_hook:wTF} checks if the argument is a valid
% file-specific hook (not, for example, |file/before|, but
-% |file/before/foo.tex|). If it is a file-specific hook, then it
+% |file/foo.tex/before|). If it is a file-specific hook, then it
% executes the \meta{true} branch, otherwise \meta{false}.
-%
-% A file-specific hook is \hook{file/\meta{position}/\meta{name}}.
-% If any of these parts don't exist, it is a general file hook or not
-% a file hook at all, so the conditional evaluates to \meta{false}.
-% Otherwise, it checks that the first part is |file| and that the
-% \meta{position} is in the \cs{c_@@_generics_file_prop}.
-%
-% A property list is used here to avoid having to worry with catcodes,
-% because \pkg{expl3}'s file name parsing turns all characters into
-% catcode-12 tokens, which might differ from hand-input letters.
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_if_file_hook:w}%
+%<latexrelease> {Standardise~generic~hook~names}
\prg_new_conditional:Npnn \@@_if_file_hook:w
- #1 / #2 / #3 \s_@@_mark { TF }
+ #1 / #2 \s_@@_mark #3 { TF }
{
- \str_if_eq:nnTF {#1} { file }
+ \@@_if_generic:nTF {#3}
{
- \bool_lazy_or:nnTF
- { \tl_if_empty_p:n {#3} }
- { \str_if_eq_p:nn {#3} { / } }
+ \str_if_eq:nnTF {#1} { file }
+ { \prg_return_true: }
{ \prg_return_false: }
- {
- \prop_if_in:NnTF \c_@@_generics_file_prop {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
}
{ \prg_return_false: }
}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_if_file_hook:w}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\prg_new_conditional:Npnn \@@_if_file_hook:w
+%<latexrelease> #1 / #2 / #3 \s_@@_mark { TF }
+%<latexrelease> {
+%<latexrelease> \str_if_eq:nnTF {#1} { file }
+%<latexrelease> {
+%<latexrelease> \bool_lazy_or:nnTF
+%<latexrelease> { \tl_if_empty_p:n {#3} }
+%<latexrelease> { \str_if_eq_p:nn {#3} { / } }
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> {
+%<latexrelease> \prop_if_in:NnTF \c_@@_generics_file_prop {#2}
+%<latexrelease> { \prg_return_true: }
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> }
+%<latexrelease> }
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_file_hook_normalize:n}
% \begin{macro}[EXP]{\@@_strip_double_slash:n,\@@_strip_double_slash:w}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_file_hook_normalize:n}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
% When a file-specific hook is found, before being declared it is
% lightly normalized by \cs{@@_file_hook_normalize:n}. The current
% implementation just replaces two consecutive slashes (|//|) by a
% single one, to cope with simple cases where the user did something
% like \verb|\def\input@path{{./mypath/}}|, in which case a hook would
-% have to be \verb|\AddToHook{file/after/./mypath//file.tex}|.
+% have to be \verb|\AddToHook{file/./mypath//file.tex/after}|.
% \begin{macrocode}
-\cs_new:Npn \@@_file_hook_normalize:n #1
- { \@@_strip_double_slash:n {#1} }
-\cs_new:Npn \@@_strip_double_slash:n #1
- { \@@_strip_double_slash:w #1 // \s_@@_mark }
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_file_hook_normalize:n}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\cs_new:Npn \@@_file_hook_normalize:n #1
+%<latexrelease> { \@@_strip_double_slash:n {#1} }
+%<latexrelease>\cs_new:Npn \@@_strip_double_slash:n #1
+%<latexrelease> { \@@_strip_double_slash:w #1 // \s_@@_mark }
% \end{macrocode}
% This function is always called after testing if the argument is a
% file hook with \cs{@@_if_file_hook:wTF}, so we can assume it has
-% three parts (it is either \verb|file/before/...| or
-% \verb|file/after/...|), so we use \verb|#1/#2/#3 //| instead of just
+% three parts (it is either \verb|file/.../before| or
+% \verb|file/.../after|), so we use \verb|#1/#2/#3 //| instead of just
% \verb|#1 //| to prevent losing a slash if the file name is empty.
% \changes{v1.0h}{2021/01/07}{Assume hook name has at least three
% nonempty parts (gh/464)}
% \begin{macrocode}
-\cs_new:Npn \@@_strip_double_slash:w #1/#2/#3 // #4 \s_@@_mark
- {
- \tl_if_empty:nTF {#4}
- { #1/#2/#3 }
- { \@@_strip_double_slash:w #1/#2/#3 / #4 \s_@@_mark }
- }
+%<latexrelease>\cs_new:Npn \@@_strip_double_slash:w #1/#2/#3 // #4 \s_@@_mark
+%<latexrelease> {
+%<latexrelease> \tl_if_empty:nTF {#4}
+%<latexrelease> { #1/#2/#3 }
+%<latexrelease> { \@@_strip_double_slash:w #1/#2/#3 / #4 \s_@@_mark }
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\c_@@_generics_prop}
-% Property list holding the generic names. We don't provide any user
-% interface to this as this is meant to be static.
+% \begin{macro}{
+% \c_@@_generic_cmd/./before_tl,\c_@@_generic_cmd/./after_tl,
+% \c_@@_generic_env/./before_tl,\c_@@_generic_env/./after_tl,
+% \c_@@_generic_file/./before_tl,\c_@@_generic_file/./after_tl,
+% \c_@@_generic_package/./before_tl,\c_@@_generic_package/./after_tl,
+% \c_@@_generic_class/./before_tl,\c_@@_generic_class/./after_tl,
+% \c_@@_generic_include/./before_tl,\c_@@_generic_include/./after_tl,
+% \c_@@_generic_env/./begin_tl,\c_@@_generic_env/./end_tl,
+% \c_@@_generic_include/./end_tl
+% }
+% Token lists defining the possible generic hooks. We don't provide
+% any user interface to this as this is meant to be static.
% \begin{description}
% \item[\texttt{cmd}]
% The generic hooks used for commands.
@@ -3048,28 +3445,65 @@
% The generic hooks used when loading a file
% \end{description}
% \begin{macrocode}
-\prop_const_from_keyval:Nn \c_@@_generics_prop
- {cmd=,env=,file=,package=,class=,include=}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\c_@@_generics_prop}%
+%<latexrelease> {Standardise~generic~hook~names}
+\clist_map_inline:nn { cmd , env , file , package , class , include }
+ {
+ \tl_const:cn { c_@@_generic_#1/./before_tl } { + }
+ \tl_const:cn { c_@@_generic_#1/./after_tl } { - }
+ }
+\tl_const:cn { c_@@_generic_env/./begin_tl } { + }
+\tl_const:cn { c_@@_generic_env/./end_tl } { + }
+\tl_const:cn { c_@@_generic_include/./end_tl } { - }
+% \end{macrocode}
+%
+% Deprecated generic hooks:
+% \begin{macrocode}
+\clist_map_inline:nn { file , package , class , include }
+ {
+ \tl_const:cn { c_@@_deprecated_#1/./before_tl } { }
+ \tl_const:cn { c_@@_deprecated_#1/./after_tl } { }
+ }
+\tl_const:cn { c_@@_deprecated_include/./end_tl } { }
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_prop}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_prop
+%<latexrelease> {cmd=,env=,file=,package=,class=,include=}
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c_@@_generics_reversed_ii_prop,
% \c_@@_generics_reversed_iii_prop,
% \c_@@_generics_file_prop}
-% Some of the generic hooks are supposed to use reverse ordering, these are
-% the following (only the second or third sub-component is checked):
+% The following generic hooks are supposed to use reverse ordering
+% (the |ii| and |iii| names are kept for the deprecation cycle):
% \begin{macrocode}
-\prop_const_from_keyval:Nn \c_@@_generics_reversed_ii_prop {after=,end=}
-\prop_const_from_keyval:Nn \c_@@_generics_reversed_iii_prop {after=}
-\prop_const_from_keyval:Nn \c_@@_generics_file_prop {before=,after=}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\c_@@_generics_reversed_ii_prop}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_reversed_ii_prop}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_reversed_ii_prop {after=,end=}
+%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_reversed_iii_prop {after=}
+%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_file_prop {before=,after=}
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hook_gremove_code:nn}
% \begin{macro}{\@@_gremove_code:nn}
-%
+%
% With \cs{hook_gremove_code:nn}\Arg{hook}\Arg{label} any code
% for \meta{hook} stored under \meta{label} is removed.
+% \changes{v1.0o}{2021/07/22}{Do not queue removals (gh/625)}
% \begin{macrocode}
\cs_new_protected:Npn \hook_gremove_code:nn #1 #2
{ \@@_normalize_hook_args:Nnn \@@_gremove_code:nn {#1} {#2} }
@@ -3101,27 +3535,13 @@
{
% \end{macrocode}
% If the label is |top-level| then clear the token list, as all code
-% there is under the same label. Marked removal is not implemented
-% for |top-level| because it is hard to reliably know that no code
-% was added to \cs{@@_toplevel\textvisiblespace\meta{hook}} (granted that
-% an empty code could be interpreted as that, but then it differs in
-% behaviour from other labels, in which an empty chunk is still valid
-% for removal). Besides, it doesn't make much (if any) sense for
-% packages to remove |top-level| code. So here the chunk is just
-% cleared unconditionally.
+% there is under the same label.
% \begin{macrocode}
\str_if_eq:nnTF {#2} { top-level }
{ \@@_tl_gclear:c { @@_toplevel~#1 } }
{
-% \end{macrocode}
-% Otherwise check if the label being removed exists in the code pool.
-% If it does, just call \cs{@@_gremove_code_do:nn} to do the removal,
-% otherwise mark it to be removed.
-% \begin{macrocode}
- \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
- { \@@_gremove_code_do:nn }
- { \@@_mark_removal:nn }
- {#1} {#2}
+ \prop_gpop:cnNF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+ { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} }
}
}
% \end{macrocode}
@@ -3132,82 +3552,21 @@
}
% \end{macrocode}
%
-% If the code pool for this hook doesn't exist it means that nothing
-% tried to add to it before, so we just queue this removal order for
-% later.
-% \begin{macrocode}
- { \@@_mark_removal:nn {#1} {#2} }
- }
-% \end{macrocode}
-%
-% \begin{macro}{\@@_gremove_code_do:nn}
-% Remove code for a given label.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_gremove_code_do:nn #1 #2
- { \prop_gremove:cn { g_@@_#1_code_prop } {#2} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_mark_removal:nn}
-% Marks \meta{label} (\verb=#2=) to be removed from \meta{hook}
-% (\verb=#1=). The number of removals should be fairly small, and
-% \cs{tl_gremove_once:Nx} is fairly efficient even for longer token
-% lists, so we use a single global token list, rather than one for
-% each hook.
-%
-% A hand-crafted token list is used here because property lists don't
-% hold repeated items, so multiple usages of \cs{@@_mark_removal:nn}
-% would be cancelled by a single \cs{@@_unmark_removal:nn}.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_mark_removal:nn #1 #2
- {
- \tl_gput_right:Nx \g_@@_removal_list_tl
- { \@@_removal_tl:nn {#1} {#2} }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_unmark_removal:nn}
-% Unmarks \meta{label} (\verb=#2=) to be removed from \meta{hook}
-% (\verb=#1=). \cs{tl_gremove_once:Nx} is used rather than
-% \cs{tl_gremove_all:Nx} so that two additions are needed to cancel
-% two marked removals, rather than only one.
+% If the code pool for this hook doesn't exist, show a warning:
% \begin{macrocode}
-\cs_new_protected:Npn \@@_unmark_removal:nn #1 #2
- {
- \tl_gremove_once:Nx \g_@@_removal_list_tl
- { \@@_removal_tl:nn {#1} {#2} }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[TF]{\@@_if_marked_removal:nn}
-% Checks if the \cs{g_@@_removal_list_tl} contains the current
-% \meta{label} (\verb=#2=) and \meta{hook} (\verb=#1=).
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \@@_if_marked_removal:nn #1 #2 { TF }
- {
- \exp_args:NNx \tl_if_in:NnTF \g_@@_removal_list_tl
- { \@@_removal_tl:nn {#1} {#2} }
- { \prg_return_true: } { \prg_return_false: }
+ {
+ \@@_if_deprecated_generic:nTF {#1}
+ {
+ \@@_deprecated_generic_warn:n {#1}
+ \@@_do_deprecated_generic:Nn \@@_gremove_code:nn {#1} {#2}
+ }
+ { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} }
+ }
}
% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}[rEXP]{\@@_removal_tl:nn}
-% Builds a token list with \verb=#1= and \verb=#2= which can only be
-% matched by \verb=#1= and \verb=#2=. The |&|$_4$ anchors a removal,
-% so that \verb=#1= can't be mistaken by \verb=#2= and vice versa, and
-% the two |$|$_3$ delimit the two arguments
-% \begin{macrocode}
-\cs_new:Npn \@@_removal_tl:nn #1 #2
- { & \tl_to_str:n {#2} $ \tl_to_str:n {#1} $ }
-% \end{macrocode}
% \end{macro}
%
-%
% \begin{macro}{
% \g_@@_??_code_prop,
% \@@~??,
@@ -3263,6 +3622,13 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_gset_rule:nnnn #1#2#3#4
{
+ \@@_if_deprecated_generic:nT {#1}
+ {
+ \@@_deprecated_generic_warn:n {#1}
+ \@@_do_deprecated_generic:Nn \@@_gset_rule:nnnn {#1}
+ {#2} {#3} {#4}
+ \exp_after:wN \use_none:nnnnnnnnn \use_none:n
+ }
% \end{macrocode}
% First we ensure the basic data structure of the hook exists:
% \begin{macrocode}
@@ -3399,12 +3765,12 @@
% |#1| is lexically greater, and \cs{use_iii:nn} otherwise.
% \begin{macrocode}
\cs_new:Npn \@@_if_label_case:nnnnn #1#2
- {
- \cs:w use_
- \if_case:w \@@_str_compare:nn {#1} {#2}
- i \or: ii \else: iii \fi: :nnn
- \cs_end:
- }
+ {
+ \cs:w use_
+ \if_case:w \@@_str_compare:nn {#1} {#2}
+ i \or: ii \else: iii \fi: :nnn
+ \cs_end:
+ }
% \end{macrocode}
% \end{macro}
%
@@ -3440,7 +3806,7 @@
}
% \end{macrocode}
% If we are debugging we show results hook by hook for all hooks
-% that have data.
+% that have data.
% \begin{macrocode}
\@@_debug:n
{ \iow_term:x{^^JAll~ initialized~ (non-empty)~ hooks:}
@@ -3492,7 +3858,7 @@
% \begin{macrocode}
\@@_if_usable:nT {#1}
{
- \prop_if_empty:cTF {g_@@_#1_code_prop}
+ \prop_if_empty:cTF { g_@@_#1_code_prop }
{
\@@_tl_gset:co { @@~#1 }
{
@@ -3503,11 +3869,11 @@
{
% \end{macrocode}
% By default the algorithm sorts the code chunks and then saves the
-% result in a token list for fast execution by adding the code one
-% after another using \cs{tl_gput_right:NV}. When we sort code for
+% result in a token list for fast execution; this is done by adding the code chunks
+% one after another, using \cs{tl_gput_right:NV}. When we sort code for
% a reversed hook, all we have to do is to add the code chunks in
% the opposite order into the token list. So all we have to do
-% in preparation is to change two definitions used later on.
+% in preparation is to change two definitions that are used later on.
% \begin{macrocode}
\@@_if_reversed:nTF {#1}
{ \cs_set_eq:NN \@@_tl_gput:Nn \@@_tl_gput_left:Nn
@@ -3518,8 +3884,9 @@
%
% When sorting, some relations (namely \verb|voids|) need to
% act destructively on the code property lists to remove code that
-% shouldn't appear in the sorted hook token list, so we temporarily
-% save the old code property list so that it can be restored later.
+% shouldn't appear in the sorted hook token list, so we make a copy
+% of the code property list that we can safely work on without
+% changing the main one.
% \begin{macrocode}
\prop_set_eq:Nc \l_@@_work_prop { g_@@_#1_code_prop }
\@@_initialize_single:ccn
@@ -3606,8 +3973,8 @@
% alphanumeric labels. As usual Don's data structures are chosen in
% a way that one can omit a lot of tests and I have mimicked that as
% far as possible. The result is a restriction I do not test for at
-% the moment: a label can't be equal to the number 0! \fmi{Needs
-% checking for, just in case ... maybe}
+% the moment: a label can't be equal to the number 0!
+% \fmiinline{Needs checking for, just in case ... maybe}
%
% ^^A #1 <- \@@~#1
% ^^A #2 <- \g_@@_#1_labels_clist
@@ -3626,11 +3993,11 @@
% \begin{macrocode}
\tl_set:Nn \l_@@_cur_hook_tl {#3}
% \end{macrocode}
-%
+%
% We loop over the property list holding the code and record all
-% labels listed there. Only rules for those labels are of interest
+% the labels listed there. Only the rules for those labels are of interest
% to us. While we are at it we count them (which gives us the $N$
-% in Knuth's algorithm. The prefix |label_| is added to the variables
+% in Knuth's algorithm). The prefix |label_| is added to the variables
% to ensure that labels named |front|, |rear|, |labels|, or |return|
% don't interact with our code.
% \begin{macrocode}
@@ -3642,11 +4009,11 @@
\seq_clear_new:c { \@@_seq_csname:n {##1} }
}
% \end{macrocode}
-% Steps T2 and T3: Sort the relevant rules into the data structure\ldots
-%
+% Steps T2 and T3: Here we sort the relevant rules into the data structure\ldots
+%
% This loop constitutes a square matrix of the labels in
% \cs{l_@@_work_prop} in the
-% vertical and the horizontal directions. However since the rule
+% vertical and the horizontal directions. However, since the rule
% $l_A\meta{rel}l_B$ is the same as $l_B\meta{rel}^{-1}l_A$ we can cut
% the loop short at the diagonal of the matrix (\emph{i.e.}, when
% both labels are equal), saving a good amount of time. The way the
@@ -3668,12 +4035,12 @@
}
}
% \end{macrocode}
-% Take a breath and take a look at the data structures that have
+% Now take a breath, and look at the data structures that have
% been set up:
% \begin{macrocode}
\@@_debug:n { \@@_debug_label_data:N \l_@@_work_prop }
% \end{macrocode}
-%
+%
%
% Step T4:
% \begin{macrocode}
@@ -3689,13 +4056,13 @@
}
\tl_set_eq:Nc \l_@@_front_tl { \@@_tl_csname:n { 0 } }
% \end{macrocode}
-%
+%
% \begin{macrocode}
\@@_tl_gclear:N #1
\clist_gclear:N #2
% \end{macrocode}
%
-% The whole loop combines steps T5--T7:
+% The whole loop gets combined in steps T5--T7:
% \begin{macrocode}
\bool_while_do:nn { ! \str_if_eq_p:Vn \l_@@_front_tl { 0 } }
{
@@ -3706,13 +4073,13 @@
\prop_get:NVN \l_@@_work_prop \l_@@_front_tl \l_@@_return_tl
\exp_args:NNV \@@_tl_gput:Nn #1 \l_@@_return_tl
% \end{macrocode}
-%
+%
% \begin{macrocode}
\@@_clist_gput:NV #2 \l_@@_front_tl
\@@_debug:n{ \iow_term:x{Handled~ code~ for~ \l_@@_front_tl} }
% \end{macrocode}
%
-% This is step T6 except that we don't use a pointer $P$ to move
+% This is step T6, except that we don't use a pointer $P$ to move
% through the successors, but instead use \verb=##1= of the mapping
% function.
% \begin{macrocode}
@@ -3730,7 +4097,7 @@
}
}
% \end{macrocode}
-% and step T7:
+% and here is step T7:
% \begin{macrocode}
\tl_set_eq:Nc \l_@@_front_tl
{ \@@_tl_csname:n { \l_@@_front_tl } }
@@ -3748,14 +4115,14 @@
% \end{macrocode}
%
% This is not really the information one needs in the error case
-% but will do for now \ldots \fmi{improve output on a rainy day}
+% but it will do for now \ldots \fmiinline{improve output on a rainy day}
% \begin{macrocode}
\@@_debug_label_data:N \l_@@_work_prop
\iow_term:x{====================}
}
% \end{macrocode}
-% After we have added all hook code to \verb=#1= we finish it off
-% with adding extra code for the |top-level| (\verb=#2=) and for one
+% After we have added all hook code to \verb=#1=, we finish it off
+% by adding extra code for the |top-level| (\verb=#2=) and for one
% time execution (\verb=#3=). These should normally be empty. The
% |top-level| code is added with \cs{@@_tl_gput:Nn} as that might
% change for a reversed hook (then |top-level| is the very first code
@@ -3905,10 +4272,10 @@
% \begin{macro}{\@@_apply_rule_->:nnn,\@@_apply_rule_<-:nnn}
% If we see \texttt{\detokenize{->}} we have to drop code for label
% \verb=#3= and carry on. We could do a little better and drop
-% everything for that label since it doesn't matter where we sort
-% in the empty code. However that would complicate the algorithm a
-% lot with little gain.\footnote{This also hase the advantage that
-% the result of the sorting doesn't change which might otherwise
+% everything for that label since it doesn't matter where we put
+% such empty code. However that would complicate the algorithm a
+% lot with little gain.\footnote{This also has the advantage that
+% the result of the sorting doesn't change, as it might otherwise do
% (for unrelated chunks) if we aren't careful.} So we still
% unnecessarily try to sort it in and depending on the rules that
% might result in a loop that is otherwise resolved. If that turns
@@ -3916,8 +4283,8 @@
%
% Here the code is removed from \cs{l_@@_cur_hook_tl} rather than
% \verb=#3= because the latter may be \verb=??=, and the default
-% hook doesn't store any code. Removing from \cs{l_@@_cur_hook_tl}
-% makes default rules \verb=->= and \verb=<-= work properly.
+% hook doesn't store any code. Removing it instead from \cs{l_@@_cur_hook_tl}
+% makes the default rules \verb=->= and \verb=<-= work properly.
% \begin{macrocode}
\cs_new_protected:cpn { @@_apply_rule_->:nnn } #1#2#3
{
@@ -3978,7 +4345,7 @@
%
%
% \begin{macro}{\@@_debug_label_data:N}
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \@@_debug_label_data:N #1 {
\iow_term:x{Code~ labels~ for~ sorting:}
@@ -4024,8 +4391,15 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_log:nN #1 #2
{
+ \@@_if_deprecated_generic:nT {#1}
+ {
+ \@@_deprecated_generic_warn:n {#1}
+ \@@_do_deprecated_generic:Nn \@@_log:nN {#1} #2
+ \exp_after:wN \use_none:nnnnnnnnn \use_none:nnnnn
+ }
\@@_preamble_hook:n {#1}
- \@@_log_cmd:x { ^^J ->~The~hook~'#1': }
+ \@@_log_cmd:x
+ { ^^J ->~The~ \@@_if_generic:nT {#1} { generic~ } hook~'#1': }
% \end{macrocode}
%
% \begin{macrocode}
@@ -4234,16 +4608,14 @@
%
% \begin{macro}{\@@_gput_next_code:nn,
% \@@_gput_next_do:nn,
-% \@@_gput_next_do:Nnn,
-% \@@_clear_next:n}
+% \@@_gput_next_do:Nnn}
% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_next_code:nn #1 #2
{
\@@_if_disabled:nTF {#1}
{ \msg_error:nnn { hooks } { hook-disabled } {#1} }
{
- \@@_init_structure:n {#1}
- \@@_if_usable:nTF {#1}
+ \@@_if_structure_exist:nTF {#1}
{ \@@_gput_next_do:nn {#1} {#2} }
{ \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
}
@@ -4275,13 +4647,21 @@
{ \@@_tl_gset:Nn #1 { \@@_clear_next:n {#2} } }
\@@_tl_gput_right:Nn #1
}
-\cs_new_protected:Npn \@@_clear_next:n #1
- { \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl }
% \end{macrocode}
% \end{macro}
%
%
%
+% \begin{macro}{\hook_gclear_next_code:n,\@@_clear_next:n}
+% Discard anything set up for next invocation of the hook.
+% \changes{v1.0o}{2021/07/27}{Macro made public}
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_gclear_next_code:n #1
+ { \@@_normalize_hook_args:Nn \@@_clear_next:n {#1} }
+\cs_new_protected:Npn \@@_clear_next:n #1
+ { \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl }
+% \end{macrocode}
+% \end{macro}
%
%
%
@@ -4302,44 +4682,68 @@
% the preamble. \cs{@@_preamble_hook:n} initializes the hook in the
% preamble, and is redefined to \cs{use_none:n} at |\begin{document}|.
%
-% Both versions do the same internally: check if the hook exist as
-% given, and if so use it as quickly as possible. If it doesn't
-% exist, the a call to \cs{@@_use:wn} checks for file hooks.
+% Both versions do the same thing internally: they check that the hook exists as
+% given, and if so they use it as quickly as possible.
%
% At |\begin{document}|, all hooks are initialized, and any change in
% them causes an update, so \cs{hook_use:n} can be made expandable.
% This one is better not protected so that it can expand into nothing
% if containing no code. Also important in case of generic hooks that
-% we do not generate a \cs[no-index]{relax} as a side effect of checking for a
-% csname. In contrast to the \TeX{} low-level
+% we do not generate a \cs[no-index]{relax} as a side effect of
+% checking for a csname. In contrast to the \TeX{} low-level
% \verb=\csname ...\endcsname= construct \cs{tl_if_exist:c} is
% careful to avoid this.
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\hook_use:n}
+%<latexrelease> {Standardise~generic~hook~names}
\cs_new_protected:Npn \hook_use:n #1
{
- \tl_if_exist:cTF { @@~#1 }
+ \tl_if_exist:cT { @@~#1 }
{
\@@_preamble_hook:n {#1}
\cs:w @@~#1 \cs_end:
}
- { \@@_use:wn #1 / \s_@@_mark {#1} }
}
\cs_new:Npn \@@_use_initialized:n #1
{
\if_cs_exist:w @@~#1 \cs_end:
- \else:
- \@@_use_undefined:w
+ \cs:w @@~#1 \exp_after:wN \cs_end:
\fi:
- \cs:w @@~#1 \@@_use_end:
- }
-\cs_new:Npn \@@_use_undefined:w #1 #2 @@~#3 \@@_use_end:
- {
- #1 % fi
- \@@_use:wn #3 / \s_@@_mark {#3}
}
\cs_new_protected:Npn \@@_preamble_hook:n #1
{ \@@_initialize_hook_code:n {#1} }
-\cs_new_eq:NN \@@_use_end: \cs_end:
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_use:n}
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\cs_new_protected:Npn \hook_use:n #1
+%<latexrelease> {
+%<latexrelease> \tl_if_exist:cTF { @@~#1 }
+%<latexrelease> {
+%<latexrelease> \@@_preamble_hook:n {#1}
+%<latexrelease> \cs:w @@~#1 \cs_end:
+%<latexrelease> }
+%<latexrelease> { \@@_use:wn #1 / \s_@@_mark {#1} }
+%<latexrelease> }
+%<latexrelease>\cs_new:Npn \@@_use_initialized:n #1
+%<latexrelease> {
+%<latexrelease> \if_cs_exist:w @@~#1 \cs_end:
+%<latexrelease> \else:
+%<latexrelease> \@@_use_undefined:w
+%<latexrelease> \fi:
+%<latexrelease> \cs:w @@~#1 \@@_use_end:
+%<latexrelease> }
+%<latexrelease>\cs_new:Npn \@@_use_undefined:w #1 #2 @@~#3 \@@_use_end:
+%<latexrelease> {
+%<latexrelease> #1 % fi
+%<latexrelease> \@@_use:wn #3 / \s_@@_mark {#3}
+%<latexrelease> }
+%<latexrelease>\cs_new_protected:Npn \@@_preamble_hook:n #1
+%<latexrelease> { \@@_initialize_hook_code:n {#1} }
+%<latexrelease>\cs_new_eq:NN \@@_use_end: \cs_end:
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -4360,63 +4764,121 @@
% \cs{@@_if_usable_use:n} checks if the hook exist, and calls
% \cs{@@_preamble_hook:n} if so, then uses the hook.
% \begin{macrocode}
-\cs_new:Npn \@@_use:wn #1 / #2 \s_@@_mark #3
- {
- \str_if_eq:nnTF {#1} { file }
- { \@@_try_file_hook:n {#3} }
- { } % Hook doesn't exist
- }
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_use:wn}
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_use:wn}
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\cs_new:Npn \@@_use:wn #1 / #2 \s_@@_mark #3
+%<latexrelease> {
+%<latexrelease> \str_if_eq:nnTF {#1} { file }
+%<latexrelease> { \@@_try_file_hook:n {#3} }
+%<latexrelease> { } % Hook doesn't exist
+%<latexrelease> }
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_try_file_hook:n #1
- {
- \@@_if_file_hook:wTF #1 / / \s_@@_mark
- {
- \exp_args:Ne \@@_if_usable_use:n
- { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
- }
- { \@@_if_usable_use:n {#1} } % file/ generic hook (e.g. file/before)
- }
+%<latexrelease>\cs_new_protected:Npn \@@_try_file_hook:n #1
+%<latexrelease> {
+%<latexrelease> \@@_if_file_hook:wTF #1 / \s_@@_mark {#1}
+%<latexrelease> {
+%<latexrelease> \exp_args:Ne \@@_if_usable_use:n
+%<latexrelease> { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
+%<latexrelease> }
+%<latexrelease> { \@@_if_usable_use:n {#1} } % file/ generic hook (e.g. file/before)
+%<latexrelease> }
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_if_usable_use:n #1
- {
- \tl_if_exist:cT { @@~#1 }
- {
- \@@_preamble_hook:n {#1}
- \cs:w @@~#1 \cs_end:
- }
- }
+%<latexrelease>\cs_new_protected:Npn \@@_if_usable_use:n #1
+%<latexrelease> {
+%<latexrelease> \tl_if_exist:cT { @@~#1 }
+%<latexrelease> {
+%<latexrelease> \@@_preamble_hook:n {#1}
+%<latexrelease> \cs:w @@~#1 \cs_end:
+%<latexrelease> }
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\hook_use_once:n}
-% For hooks that can and should be used only once we have a special
-% use command that remembers the hook name in
-% \cs{g_@@_execute_immediately_prop}. This has the effect that any
-% further code added to the hook is executed immediately rather
-% than stored in the hook.
+% \begin{macro}{\hook_use_once:n}
+% \begin{macro}{\@@_use_once:n}
+% For hooks that can and should be used only once we have a special
+% use command that further inhibits the hook from getting more code
+% added to it. This has the effect that any
+% further code added to the hook is executed immediately rather
+% than stored in the hook.
%
-% The code needs some gymnastics to prevent space trimming from the
-% hook name, since \cs{hook_use:n} and \cs{hook_use_once:n} are
-% documented to not trim spaces.
+% The code needs some gymnastics to prevent space trimming from the
+% hook name, since \cs{hook_use:n} and \cs{hook_use_once:n} are
+% documented to not trim spaces.
%
+% \changes{v1.0r}{2021/09/06}{Clean up after \cs{UseOneTimeHook} (gh/606)}
% \begin{macrocode}
\cs_new_protected:Npn \hook_use_once:n #1
{
- \tl_if_exist:cT { @@~#1 }
+ \@@_if_execute_immediately:nF {#1}
+ { \@@_normalize_hook_args:Nn \@@_use_once:n { \use:n {#1} } }
+ }
+\cs_new_protected:Npn \@@_use_once:n #1
+ {
+ \@@_preamble_hook:n {#1}
+ \@@_use_once_set:n {#1}
+ \@@_use_initialized:n {#1}
+ \@@_use_once_clear:n {#1}
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_use_once_set:n}
+% \begin{macro}{\@@_use_once_clear:n}
+% \cs{@@_use_once_set:n} is used before the actual hook code is
+% executed so that any usage of \cs{AddToHook} inside the hook causes
+% the code to execute immediately. Setting
+% \cs[no-index]{g_@@_\meta{hook}_reversed_tl} to |I| prevents further
+% code from being added to the hook. \cs{@@_use_once_clear:n} then
+% clears the hook so that any further call to \cs{hook_use:n} or
+% \cs{hook_use_once:n} will expand to nothing.
+% \changes{v1.0r}{2021/09/06}{Clean up after \cs{UseOneTimeHook} (gh/606)}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_use_once_set:n #1
+ { \@@_tl_gset:cn { g_@@_#1_reversed_tl } { I } }
+\cs_new_protected:Npn \@@_use_once_clear:n #1
+ {
+ \@@_tl_gclear:c { @@~#1 }
+ \@@_tl_gclear:c { @@_next~#1 }
+ \@@_tl_gclear:c { @@_toplevel~#1 }
+ \prop_gclear:c { g_@@_#1_code_prop }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_execute_immediately:n}
+% To check whether the code being added should be executed immediately (that
+% is, if the hook is a one-time hook), we check if it's usable (it
+% can't be one-time if it was not already usable), then we check that
+% \cs[no-index]{g_@@_\meta{hook}_reversed_tl} is |I|. The gymnastics
+% around \cs{if:w} is there to allow the |reversed| token list to be
+% empty.
+% \changes{v1.0r}{2021/09/06}{Macro added (gh/606)}
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_execute_immediately:n #1 { F, TF }
+ {
+ \@@_if_usable:nTF {#1}
{
- \tl_set:Nn \l_@@_return_tl {#1}
- \@@_normalize_hook_args:Nn \@@_use_once_store:n
- { \l_@@_return_tl }
- \hook_use:n {#1}
+ \exp_after:wN \@@_clean_to_scan:w
+ \if:w I \cs:w g_@@_#1_reversed_tl \cs_end:
+ \s_@@_mark \prg_return_true:
+ \else:
+ \s_@@_mark \prg_return_false:
+ \fi:
}
+ { \prg_return_false: }
}
-\cs_new_protected:Npn \@@_use_once_store:n #1
- { \prop_gput:Nnn \g_@@_execute_immediately_prop {#1} { } }
% \end{macrocode}
% \end{macro}
%
@@ -4504,9 +4966,8 @@
}
% \end{macrocode}
% \end{macro}
-%
-%
-%
+%
+%
% \begin{macro}[pTF]{\@@_if_declared:n}
%
% Internal test to check if the hook was officially declared with
@@ -4526,28 +4987,76 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \@@_if_reversed:n #1 { p , T , F , TF }
{
- \if_int_compare:w \cs:w g_@@_#1_reversed_tl \cs_end: 1 < 0 \exp_stop_f:
+ \exp_after:wN \@@_clean_to_scan:w
+ \if:w - \cs:w g_@@_#1_reversed_tl \cs_end:
+ \s_@@_mark \prg_return_true:
+ \else:
+ \s_@@_mark \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_generic:n}
+% \begin{macro}[pTF]{\@@_if_deprecated_generic:n}
+% An internal conditional that checks if a name belongs to a generic
+% hook. The deprecated version needs to check if |#3| is empty to
+% avoid returning true on \hook{file/before}, for example.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_generic:n #1 { T, TF }
+ { \@@_if_generic:w #1 / / / \s_@@_mark }
+\cs_new:Npn \@@_if_generic:w #1 / #2 / #3 / #4 \s_@@_mark
+ {
+ \cs_if_exist:cTF { c_@@_generic_#1/./#3_tl }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\prg_new_conditional:Npnn \@@_if_deprecated_generic:n #1 { T, TF }
+ { \@@_if_deprecated_generic:w #1 / / / \s_@@_mark }
+\cs_new:Npn \@@_if_deprecated_generic:w #1 / #2 / #3 / #4 \s_@@_mark
+ {
+ \cs_if_exist:cTF { c_@@_deprecated_#1/./#2_tl }
+ {
+ \tl_if_empty:nTF {#3}
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_generic_reversed:n}
+% An internal conditional that checks if a name belongs to a generic
+% reversed hook.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_generic_reversed:n #1 { T }
+ { \@@_if_generic_reversed:w #1 / / / \scan_stop: }
+\cs_new:Npn \@@_if_generic_reversed:w #1 / #2 / #3 / #4 \scan_stop:
+ {
+ \if_charcode:w - \cs:w c_@@_generic_#1/./#3_tl \cs_end:
\prg_return_true:
\else:
\prg_return_false:
\fi:
}
% \end{macrocode}
-% \end{macro}
-%
+% \end{macro}
%
% \subsection{Messages}
%
-% Hook errors are LaTeX kernel errors:
+% Hook errors are LaTeX kernel errors:
% \begin{macrocode}
\prop_gput:Nnn \g_msg_module_type_prop { hooks } { LaTeX }
% \end{macrocode}
+% \changes{v1.0q}{2021/08/27}{Internal message name changes}
% And so are kernel errors (this should move elsewhere eventually).
% \begin{macrocode}
-\prop_gput:Nnn \g_msg_module_type_prop { kernel } { LaTeX }
-%\prop_gput:Nnn \g_msg_module_name_prop { kernel } { } % <-- currently not working
+\prop_gput:Nnn \g_msg_module_type_prop { latex2e } { LaTeX }
+\prop_gput:Nnn \g_msg_module_name_prop { latex2e } { kernel }
% \end{macrocode}
-%
+%
% \begin{macrocode}
\msg_new:nnnn { hooks } { labels-incompatible }
{
@@ -4560,7 +5069,7 @@
{ LaTeX~found~two~incompatible~labels~in~the~same~hook.~
This~indicates~an~incompatibility~between~packages. }
% \end{macrocode}
-%
+%
% \begin{macrocode}
\msg_new:nnnn { hooks } { exists }
{ Hook~'#1'~ has~ already~ been~ declared. }
@@ -4568,14 +5077,14 @@
name.\\
Please~ use~ a~ different~ name~ for~ your~ hook.}
% \end{macrocode}
-%
+%
%
% \begin{macrocode}
\msg_new:nnnn { hooks } { hook-disabled }
{ Cannot~add~code~to~disabled~hook~'#1'. }
{
The~hook~'#1'~you~tried~to~add~code~to~was~previously~disabled~
- with~\iow_char:N\\hook_disable:n~or~\iow_char:N\\DisableHook,~so~
+ with~\iow_char:N\\hook_disable_generic:n~or~\iow_char:N\\DisableGenericHook,~so~
it~cannot~have~code~added~to~it.
}
% \end{macrocode}
@@ -4601,7 +5110,7 @@
{ Unknown~ relationship~ '#3'~
between~ labels~ '#2'~ and~ '#4'~
\str_if_eq:nnF {#1} {??} { ~in~hook~'#1' }. ~
- Perhaps~ a~ missspelling?
+ Perhaps~ a~ misspelling?
}
{
The~ relation~ used~ not~ known~ to~ the~ system.~ Allowed~ values~ are~
@@ -4613,7 +5122,7 @@
'unrelated'.
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\msg_new:nnnn { hooks } { misused-top-level }
{
@@ -4651,7 +5160,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\msg_new:nnn { kernel } { should-not-happen }
+\msg_new:nnn { latex2e } { should-not-happen }
{
This~should~not~happen.~#1 \\
Please~report~at~https://github.com/latex3/latex2e.
@@ -4661,32 +5170,31 @@
%
%
% \begin{macrocode}
-\msg_new:nnn { hooks } { provide-disabled }
+\msg_new:nnn { hooks } { activate-disabled }
{
- Cannot~ provide~ hook~ '#1'~ because~ it~ is~ disabled!
+ Cannot~ activate~ hook~ '#1'~ because~ it~ is~ disabled!
}
% \end{macrocode}
%
% \begin{macrocode}
-\msg_new:nnnn { hooks } { provide-error }
+\msg_new:nnn { hooks } { cannot-remove }
{
- Hook~'#1'~ already~ declared~ as~ a~
- \@@_if_reversed:nTF {#1} { reversed } { normal }~ hook!
+ Cannot~remove~chunk~'#2'~from~hook~'#1'~because~
+ \@@_if_structure_exist:nTF {#1}
+ { it~does~not~exist~in~that~hook. }
+ { the~hook~does~not~exist. }
}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { hooks } { generic-deprecated }
{
- You~ attempted~ to~ provide~ the~ hook~'#1'~ as~ a~
- \@@_if_reversed:nTF {#1} { normal } { reversed }~ hook,~ but~ it~
- was~ already~ previously~ declared~ as~ a~
- \@@_if_reversed:nTF {#1} { reversed } { normal }~ hook.~
- A~ redeclaration~ is~ not~ possible.
+ Generic~hook~'#1/#2/#3'~is~deprecated. \\
+ Use~hook~'#1/#3/#2'~instead.
}
% \end{macrocode}
%
%
-%
-%
-%
-%
% \subsection{\LaTeXe{} package interface commands}
%
%
@@ -4704,42 +5212,38 @@
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2021/06/01}%
-%<latexrelease> {\hook_provide:n}{Providing~hooks}
+%<latexrelease> {\hook_activate_generic:n}{Providing~hooks}
% \end{macrocode}
%
-% \begin{macro}{\ProvideHook,\ProvideReversedHook,\ProvideMirroredHookPair}
+% \begin{macro}{\ActivateGenericHook}
% Providing new hooks \ldots
% \changes{v1.0m}{2021/04/29}{Add \cs{ProvideHook} etc.}
+% \changes{v1.0o}{2021/08/02}{Change name}
% \begin{macrocode}
-\NewDocumentCommand \ProvideHook { m }{ \hook_provide:n {#1} }
-\NewDocumentCommand \ProvideReversedHook { m }{ \hook_provide_reversed:n {#1} }
-\NewDocumentCommand \ProvideMirroredHookPair { mm }{ \hook_provide_pair:nn {#1}{#2} }
+\NewDocumentCommand \ActivateGenericHook { m }{ \hook_activate_generic:n {#1} }
% \end{macrocode}
% \end{macro}
%
-%
-% \begin{macro}{\DisableHook}
-% Disabling a (generic) hook.
+% \begin{macro}{\DisableGenericHook}
+% Disabling a generic hook.
+% \changes{v1.0o}{2021/08/02}{Change name}
% \begin{macrocode}
-\NewDocumentCommand \DisableHook { m }{ \hook_disable:n {#1} }
+\NewDocumentCommand \DisableGenericHook { m }{ \hook_disable_generic:n {#1} }
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2020/10/01}
-%<latexrelease> {\hook_provide:n}{Providing~hooks}
+%<latexrelease> {\hook_activate_generic:n}{Providing~hooks}
%<latexrelease>
-%<latexrelease>\def \ProvideHook#1{}
-%<latexrelease>\def \ProvideReversedHook#1{}
-%<latexrelease>\def \ProvideMirroredHookPair#1#2{}
+%<latexrelease>\def \ActivateGenericHook#1{}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
%
% \begin{macro}{\AddToHook}
-%
% \begin{macrocode}
\NewDocumentCommand \AddToHook { m o +m }
{ \hook_gput_code:nnn {#1} {#2} {#3} }
@@ -4747,16 +5251,22 @@
% \end{macro}
%
% \begin{macro}{\AddToHookNext}
-%
% \begin{macrocode}
\NewDocumentCommand \AddToHookNext { m +m }
{ \hook_gput_next_code:nn {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\ClearHookNext}
+% \changes{v1.0o}{2021/07/27}{Macro added}
+% \begin{macrocode}
+\NewDocumentCommand \ClearHookNext { m }
+ { \hook_gclear_next_code:n {#1} }
+% \end{macrocode}
+% \end{macro}
+%
%
% \begin{macro}{\RemoveFromHook}
-%
% \begin{macrocode}
\NewDocumentCommand \RemoveFromHook { m o }
{ \hook_gremove_code:nn {#1} {#2} }
@@ -4766,140 +5276,11 @@
% \begin{macro}{\SetDefaultHookLabel}
% \begin{macro}{\PushDefaultHookLabel}
% \begin{macro}{\PopDefaultHookLabel}
-%
-% \fmiinline{Docu task: At some point this code for this should be moved to the
-% label section earlier and here we should keep only the interface commands.}
-%
-% \begin{macro}{\@@_curr_name_push:n,\@@_curr_name_push_aux:n}
-% \begin{macro}{\@@_curr_name_pop:}
-% \begin{macro}{\@@_end_document_label_check:}
-% The token list \cs{g_@@_hook_curr_name_tl} stores the name of the
-% current package/file to be used as label for hooks.
-% Providing a consistent interface is tricky, because packages can
-% be loaded within packages, and some packages may not use
-% \cs{SetDefaultHookLabel} to change the default label (in which
-% case \cs{@currname} is used).
-%
-% To pull that one off, we keep a stack that contains the default
-% label for each level of input. The bottom of the stack contains the
-% default label for the |top-level| (this stack should never go
-% empty). If we're building the format, set the default label to be
-% |top-level|:
-% \begin{macrocode}
-\tl_gset:Nn \g_@@_hook_curr_name_tl { top-level }
-% \end{macrocode}
-%
-% Then, in case we're in \pkg{latexrelease} we push something on
-% the stack to support roll forward. But in some rare cases,
-% \pkg{latexrelease} may be loaded inside another package (notably
-% \pkg{platexrelease}), so we'll first push the |top-level| entry:
-% \changes{v1.0i}{2021/03/18}
-% {Only add \texttt{top-level} if not already there.}
-% \begin{macrocode}
-%<latexrelease>\seq_if_empty:NT \g_@@_name_stack_seq
-%<latexrelease> { \seq_gput_right:Nn \g_@@_name_stack_seq { top-level } }
-% \end{macrocode}
-% then we dissect the \cs{@currnamestack}, adding \cs{@currname} to
-% the stack:
-% \changes{v1.0f}{2020/11/24}{Support for roll forward (gh/434)}
-% \begin{macrocode}
-%<latexrelease>\cs_set_protected:Npn \@@_tmp:w #1 #2 #3
-%<latexrelease> {
-%<latexrelease> \quark_if_recursion_tail_stop:n {#1}
-%<latexrelease> \seq_gput_right:Nn \g_@@_name_stack_seq {#1}
-%<latexrelease> \@@_tmp:w
-%<latexrelease> }
-%<latexrelease>\exp_after:wN \@@_tmp:w \@currnamestack
-%<latexrelease> \q_recursion_tail \q_recursion_tail
-%<latexrelease> \q_recursion_tail \q_recursion_stop
-% \end{macrocode}
-% and finally set the default label to be the \cs{@currname}:
-% \changes{v1.0i}{2021/03/18}
-% {Remove the (empty) \enquote{top-level} from \cs{@currnamestack}.}
-% \begin{macrocode}
-%<latexrelease>\tl_gset:Nx \g_@@_hook_curr_name_tl { \@currname }
-%<latexrelease>\seq_gpop_right:NN \g_@@_name_stack_seq \l_@@_tmpa_tl
-% \end{macrocode}
-%
-% Two commands keep track of the stack: when a file is input,
-% \cs{@@_curr_name_push:n} pushes the current default label to the
-% stack, and sets the new default label in one go:
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_curr_name_push:n #1
- { \exp_args:Nx \@@_curr_name_push_aux:n { \@@_make_name:n {#1} } }
-\cs_new_protected:Npn \@@_curr_name_push_aux:n #1
- {
- \tl_if_blank:nTF {#1}
- { \msg_error:nn { hooks } { no-default-label } }
- {
- \str_if_eq:nnTF {#1} { top-level }
- {
- \msg_error:nnnnn { hooks } { set-top-level }
- { to } { PushDefaultHookLabel } {#1}
- }
- {
- \seq_gpush:NV \g_@@_name_stack_seq \g_@@_hook_curr_name_tl
- \tl_gset:Nn \g_@@_hook_curr_name_tl {#1}
- }
- }
- }
-% \end{macrocode}
-% and when an input is over, the topmost item of the stack is popped,
-% since the label will not be used again, and \cs{g_@@_hook_curr_name_tl}
-% is updated to the now topmost item of the stack:
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_curr_name_pop:
- {
- \seq_gpop:NNTF \g_@@_name_stack_seq \l_@@_return_tl
- { \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl }
- { \msg_error:nn { hooks } { extra-pop-label } }
- }
-% \end{macrocode}
-%
-% At the end of the document we want to check if there was no
-% \cs{@@_curr_name_push:n} without a matching \cs{@@_curr_name_pop:}
-% (not a critical error, but it might indicate that something else is
-% not quite right):
-% \begin{macrocode}
-\tl_gput_right:Nn \@kernel@after@enddocument@afterlastpage
- { \@@_end_document_label_check: }
-\cs_new_protected:Npn \@@_end_document_label_check:
- {
- \seq_gpop:NNT \g_@@_name_stack_seq \l_@@_return_tl
- {
- \msg_error:nnx { hooks } { missing-pop-label }
- { \g_@@_hook_curr_name_tl }
- \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl
- \@@_end_document_label_check:
- }
- }
-% \end{macrocode}
-%
-% The token list \cs{g_@@_hook_curr_name_tl} is but a mirror of the top
-% of the stack.
-%
% Now define a wrapper that replaces the top of the stack with the
% argument, and updates \cs{g_@@_hook_curr_name_tl} accordingly.
% \begin{macrocode}
\NewDocumentCommand \SetDefaultHookLabel { m }
- {
- \seq_if_empty:NTF \g_@@_name_stack_seq
- {
- \msg_error:nnnnn { hooks } { set-top-level }
- { for } { SetDefaultHookLabel } {#1}
- }
- { \exp_args:Nx \@@_set_default_label:n { \@@_make_name:n {#1} } }
- }
-\cs_new_protected:Npn \@@_set_default_label:n #1
- {
- \str_if_eq:nnTF {#1} { top-level }
- {
- \msg_error:nnnnn { hooks } { set-top-level }
- { to } { SetDefaultHookLabel } {#1}
- }
- { \tl_gset:Nn \g_@@_hook_curr_name_tl {#1} }
- }
-% \end{macrocode}
+ { \@@_set_default_hook_label:n {#1} }
%
% The label is only automatically updated with \cs{@onefilewithoptions}
% (\cs{usepackage} and \cs{documentclass}), but some packages, like
@@ -4907,7 +5288,7 @@
% \cs{usetikzlibrary} that are wrappers around \cs{input}, so they
% inherit the default label currently in force (usually |top-level|,
% but it may change if loaded in another package). To provide a
-% package-like behaviour also for hooks in these files, we provide
+% package-like behavior also for hooks in these files, we provide
% high-level access to the default label stack.
% \begin{macrocode}
\NewDocumentCommand \PushDefaultHookLabel { m }
@@ -4935,9 +5316,6 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
%
%
@@ -4961,7 +5339,7 @@
% \end{macro}
%
% \begin{macro}{\DebugHooksOn,\DebugHooksOff}
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \DebugHooksOn { \hook_debug_on: }
\cs_new_protected:Npn \DebugHooksOff { \hook_debug_off: }
@@ -4971,7 +5349,7 @@
%
%
% \begin{macro}{\DeclareHookRule}
-%
+%
% \begin{macrocode}
\NewDocumentCommand \DeclareHookRule { m m m m }
{ \hook_gset_rule:nnnn {#1}{#2}{#3}{#4} }
@@ -5001,7 +5379,7 @@
% \begin{macro}[EXP]{\IfHookEmptyTF}
% Here we avoid the overhead of \pkg{xparse}, since \cs{IfHookEmptyTF}
% is used in \cs{end} (that is, every \LaTeX{} environment). As a
-% further optimisation, use \cs{let} rather than \cs{def} to avoid one
+% further optimization, use \cs{let} rather than \cs{def} to avoid one
% expansion step.
% \begin{macrocode}
\cs_new_eq:NN \IfHookEmptyTF \hook_if_empty:nTF
@@ -5025,6 +5403,111 @@
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
+% \subsection{Deprecated that needs cleanup at some point}
+%
+% \changes{v1.0p}{2021/08/20}{Added deprecation warnings for
+% old generic hook commands (gh/638)}
+%
+% \begin{macro}{
+% \hook_disable:n,
+% \hook_provide:n,
+% \hook_provide_reversed:n,
+% \hook_provide_pair:nn,
+% \@@_activate_generic_reversed:n,
+% \@@_activate_generic_pair:nn,
+% }
+% Deprecated.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_disable:n
+ {
+ \@@_deprecated_warn:nn
+ { hook_disable:n }
+ { hook_disable_generic:n }
+ \hook_disable_generic:n
+ }
+\cs_new_protected:Npn \hook_provide:n
+ {
+ \@@_deprecated_warn:nn
+ { hook_provide:n }
+ { hook_activate_generic:n }
+ \hook_activate_generic:n
+ }
+\cs_new_protected:Npn \hook_provide_reversed:n
+ {
+ \@@_deprecated_warn:nn
+ { hook_provide_reversed:n }
+ { hook_activate_generic:n }
+ \@@_activate_generic_reversed:n
+ }
+\cs_new_protected:Npn \hook_provide_pair:nn
+ {
+ \@@_deprecated_warn:nn
+ { hook_provide_pair:nn }
+ { hook_activate_generic:n }
+ \@@_activate_generic_pair:nn
+ }
+\cs_new_protected:Npn \@@_activate_generic_reversed:n #1
+ { \@@_normalize_hook_args:Nn \@@_activate_generic:nn {#1} { - } }
+\cs_new_protected:Npn \@@_activate_generic_pair:nn #1#2
+ { \hook_activate_generic:n {#1} \@@_activate_generic_reversed:n {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \DisableHook,
+% \ProvideHook,
+% \ProvideReversedHook,
+% \ProvideMirroredHookPair,
+% }
+% Deprecated.
+% \begin{macrocode}
+\cs_new_protected:Npn \DisableHook
+ {
+ \@@_deprecated_warn:nn
+ { DisableHook }
+ { DisableGenericHook }
+ \hook_disable_generic:n
+ }
+\cs_new_protected:Npn \ProvideHook
+ {
+ \@@_deprecated_warn:nn
+ { ProvideHook }
+ { ActivateGenericHook }
+ \hook_activate_generic:n
+ }
+\cs_new_protected:Npn \ProvideReversedHook
+ {
+ \@@_deprecated_warn:nn
+ { ProvideReversedHook }
+ { ActivateGenericHook }
+ \@@_activate_generic_reversed:n
+ }
+\cs_new_protected:Npn \ProvideMirroredHookPair
+ {
+ \@@_deprecated_warn:nn
+ { ProvideMirroredHookPair }
+ { ActivateGenericHook }
+ \@@_activate_generic_pair:nn
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_deprecated_warn:nn}
+% Warns about a deprecation, telling what should be used instead.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_deprecated_warn:nn #1 #2
+ { \msg_warning:nnnn { hooks } { deprecated } {#1} {#2} }
+\msg_new:nnn { hooks } { deprecated }
+ {
+ Command~\iow_char:N\\#1~is~deprecated~and~will~be~removed~in~a~
+ future~release. \\ \\
+ Use~\iow_char:N\\#2~instead.
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
%
% \subsection{Internal commands needed elsewhere}
%
@@ -5068,7 +5551,7 @@
%<latexrelease>\def \NewReversedHook#1{}
%<latexrelease>\def \NewMirroredHookPair#1#2{}
%<latexrelease>
-%<latexrelease>\def \DisableHook #1{}
+%<latexrelease>\def \DisableGenericHook #1{}
%<latexrelease>
%<latexrelease>\long\def\AddToHookNext#1#2{}
%<latexrelease>
@@ -5105,6 +5588,6 @@
% \Finale
%
%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%