[latex3-commits] [git/LaTeX3-latex3-latex2e] lthooks: added the version with dot-notation (1d897b16)
Frank Mittelbach
frank.mittelbach at latex-project.org
Thu Jul 9 21:57:41 CEST 2020
Repository : https://github.com/latex3/latex2e
On branch : lthooks
Link : https://github.com/latex3/latex2e/commit/1d897b16a01bf2533baace4efd59952e6883d9e0
>---------------------------------------------------------------
commit 1d897b16a01bf2533baace4efd59952e6883d9e0
Author: Frank Mittelbach <frank.mittelbach at latex-project.org>
Date: Thu Jul 9 21:57:41 2020 +0200
added the version with dot-notation
>---------------------------------------------------------------
1d897b16a01bf2533baace4efd59952e6883d9e0
base/lthooks.dtx | 414 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 334 insertions(+), 80 deletions(-)
diff --git a/base/lthooks.dtx b/base/lthooks.dtx
index cc33e446..577d9529 100644
--- a/base/lthooks.dtx
+++ b/base/lthooks.dtx
@@ -17,7 +17,7 @@
% for those people who are interested or want to report an issue.
%
% \begin{macrocode}
-\providecommand\lthooksversion{v0.8r}
+\providecommand\lthooksversion{v0.8s}
\providecommand\lthooksdate{2020/07/09}
% \end{macrocode}
%
@@ -122,8 +122,8 @@
% \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 is a hook provided as part of a package it is suggested
+% that the \meta{hook} 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
@@ -201,7 +201,8 @@
% Adds \meta{code} to the \meta{hook} labeled by \meta{label}. If
% the optional argument \meta{label} is not provided, if \cs{AddToHook}
% is used in a package/class, then the current
-% package/class name is used, otherwise \hook{top-level} is used.
+% package/class name is used, otherwise \hook{top-level} is
+% used~(see section~\ref{sec:default-label}).
%
% If there already exists code under the \meta{label} then the new
% \meta{code} is appended to the existing one (even if this is a reversed hook).
@@ -210,29 +211,13 @@
%
% The hook doesn't have to exist for code to be added to
% it. However, if it is not declared later then obviously the
-% added \meta{code} will nevery be executed This
+% added \meta{code} will never be executed. This
% allows for hooks to work regardless of package loading order and
% enables packages to add to hook of other packages without
% worrying whether they are actually used in the current document.
% See section~\ref{sec:querying}.
% \end{function}
%
-% It is best practice to use \cs{AddToHook} in packages or classes
-% without specifying a \meta{label} because then the package or
-% class name is automatically used which is helpful if rules are
-% needed, etc.
-%
-% Using an explicit \meta{label} is only necessary in very specific
-% situations, e.g., if you want to add several chunks of code into a
-% single hook and have them placed in different parts of the hook
-% (by providing some rules).
-%
-% The other case is when you develop a larger package with several
-% sub-packages. In that case you may want to use the same
-% \meta{label} throughout of the sub-packages in order to avoid
-% that the labels change if you internally reorganize your code.
-%
-%
% \begin{function}{\RemoveFromHook}
% \begin{syntax}
% \cs{RemoveFromHook} \Arg{hook}\oarg{label}
@@ -272,8 +257,8 @@
% changes for no good reason.
%
% The above is only needed if one wants to typeset several quotes in a
-% smaller typefac. If the hook is only needed once then
-% \cs{AddToHookNext} is simpler as that resets itself after use.
+% smaller typeface. If the hook is only needed once then
+% \cs{AddToHookNext} is simpler, because it resets itself after one use.
%
%
% \begin{function}{\AddToHookNext}
@@ -296,6 +281,76 @@
% \end{function}\footnotetext{There is
% no mechanism to reorder such code chunks (or delete them).}
%
+% \subsection{Default labels}
+% \label{sec:default-label}
+%
+% It is best practice to use \cs{AddToHook} in packages or classes
+% \emph{without specifying a \meta{label}} because then the package
+% or class name is automatically used, which is helpful if rules are
+% needed, and avoids mistyping the \meta{label}.
+%
+% Using an explicit \meta{label} is only necessary in very specific
+% situations, e.g., if you want to add several chunks of code into a
+% single hook and have them placed in different parts of the hook
+% (by providing some rules).
+%
+% The other case is when you develop a larger package with several
+% sub-packages. In that case you may want to use the same
+% \meta{label} throughout the sub-packages in order to avoid
+% that the labels change if you internally reorganize your code.
+%
+% It is not enforced, but highly recommended that the label contains the
+% package name to easily identify the source of the code chunk and to
+% prevent clashes. This should be the standard practice, so this hook
+% management code provides a shortcut to refer to the current package
+% name in a \meta{label}. In a \meta{label}, a single dot (|.|), or a
+% dot followed by a slash (|./|) denote the \meta{default label}
+% (usually the current package or class
+% name---see~\cs{DeclareDefaultHookLabel}).
+% A \enquote{|.|} or \enquote{|./|} anywhere else in a \meta{label} is
+% treated literally and not replaced.
+% For example, inside the package \texttt{mypackage.sty}, the default
+% label is \texttt{mypackage}, so the instructions:
+% \begin{verbatim}
+% \AddToHook {hook}[.]{code} % Same as \AddToHook {hook}{code}
+% \AddToHook {hook}[./sub]{code}
+% \end{verbatim}
+% are equivalent to:
+% \begin{verbatim}
+% \AddToHook {hook}[mypackage]{code}
+% \AddToHook {hook}[mypackage/sub]{code}
+% \end{verbatim}
+%
+% This syntax is available in all \meta{label} arguments, both in
+% the \LaTeXe{} interface, and the \LaTeX3 interface described in
+% section~\ref{sec:l3hook-interface}.
+%
+% The \meta{default label} is automatically set to the name of the
+% current package or class (using \cs{@currname}). If \cs{@currname}
+% is not set (because the hook command is used outside of a package, or
+% the current file wasn't loaded with \cs{usepackage} or
+% \cs{documentclass}), then the \texttt{top-level} is used as the
+% \meta{default label}.
+%
+% In some cases, for example in large packages, one may want to separate
+% it in logical parts, but still use the main package name as
+% \meta{label}, then the \meta{default label} can be set using
+% \cs{DeclareDefaultHookLabel}:
+%
+% \begin{function}{\DeclareDefaultHookLabel}
+% \begin{syntax}
+% \cs{DeclareDefaultHookLabel} \Arg{default label}
+% \end{syntax}
+% Sets the \meta{default label} to be used in \meta{label} arguments.
+% If \cs{DeclareDefaultHookLabel} is not used in the
+% current package, \cs{@currname} is used instead. If \cs{@currname}
+% is not set, the code is assumed to be in the main document, in which
+% case \texttt{top-level} is used.
+%
+% The effect of \cs{DeclareDefaultHookLabel} holds for the current
+% file, and is reset to the previous value when the file is closed.
+% \end{function}
+%
%
% \subsubsection{Defining relations between hook code}
%
@@ -341,14 +396,15 @@
% \item[\texttt{incompatible-warning}]
%
% Only code for either \meta{label1} or \meta{label2} can appear
-% for that hook (a way to say that two packages (or parts of
-% them) are incompatible). A warning is raised if both labels
+% for that hook (a way to say that two packages---or parts of
+% them---are incompatible). A warning is raised if both labels
% appear in the same hook.
%
% \item[\texttt{incompatible-error}]
%
% Like \texttt{incompatible-error} but instead of a warning a
-% \LaTeX{} error is raised.
+% \LaTeX{} error is raised, and the code for both labels are
+% dropped from that hook until the conflict is resolved.
%
% \item[\texttt{removes}]
%
@@ -489,6 +545,7 @@
%
%
% \subsection{L3 programming layer (\texttt{expl3}) interfaces}
+% \label{sec:l3hook-interface}
%
%
% This is a quick summary of the \LaTeX3 programming interfaces for
@@ -532,9 +589,7 @@
% \fmi{better L3 name?}
% \end{function}
%
-% \begin{function}
-% {\hook_gput_code:nnn,\hook_gput_code:non,
-% \hook_gput_code:nnv,\hook_gput_code:nov}
+% \begin{function}{\hook_gput_code:nnn}
% \begin{syntax}
% \cs{hook_gput_code:nnn} \Arg{hook} \Arg{label} \Arg{code}
% \end{syntax}
@@ -546,6 +601,9 @@
% another package) then the convention is to use the package name
% as the \meta{label} not some internal module name or some other
% arbitrary string.
+%
+% The \meta{label} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
% \end{function}
%
% \begin{function}
@@ -566,19 +624,24 @@
%
-% \begin{function}{\hook_gremove_code:nn,\hook_gremove_code:no}
+% \begin{function}{\hook_gremove_code:nn}
% \begin{syntax}
% \cs{hook_gremove_code:nn} \Arg{hook} \Arg{label}
% \end{syntax}
-% Removes any code for \meta{hook} labeled \meta{label}. It is okay
-% if no code has been set up under \meta{label}.\fmi{Is it? Or
-% should this generate an error?}
+% 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 the second 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, so think twice before using
% that!
%
+% The \meta{label} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
% \end{function}
@@ -589,6 +652,11 @@
% Relate \meta{label1} with \meta{label2} when used in \meta{hook}.
% See \cs{DeclareHookRule} for the allowed \meta{relation}s.
% If \meta{hook} is \texttt{??} a default rule is specified.
+%
+% The \meta{label} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% The dot-syntax is parsed in both \meta{label} arguments, but it
+% usually makes sense to be used in only one of them.
% \end{function}
%
% \begin{function}[pTF]{\hook_if_empty:n}
@@ -1159,6 +1227,15 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\g_@@_hook_curr_name_tl,\g_@@_name_stack_seq}
+% Default label used for hook commands, and a stack to keep track of
+% packages within packages.
+% \begin{macrocode}
+\tl_new:N \g_@@_hook_curr_name_tl
+\seq_new:N \g_@@_name_stack_seq
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\tl_gremove_once:Nx}
% Some variants of \pkg{expl3} functions.
% \begin{macrocode}
@@ -1166,6 +1243,13 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\s_@@_mark}
+% Scan mark used for delimited arguments.
+% \begin{macrocode}
+\scan_new:N \s_@@_mark
+% \end{macrocode}
+% \end{macro}
+%
%
% \subsection{Providing new hooks}
%
@@ -1296,7 +1380,7 @@
% \end{macro}
-% \begin{macro}{\@@_provide_legacy_interface:n}
+% \begin{macro}{\@@_provide_legacy_interface:n}
% The \LaTeX{} legacy concept for hooks uses with hooks the
% following naming scheme in the code: \cs{@...hook}.
%
@@ -1310,24 +1394,28 @@
% unnecessary expansion on each invocation in the document but
% keeps the \LaTeXe{} and the L3 coding side properly separated.}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_provide_legacy_interface:n #1 {
+\cs_new_protected:Npn \@@_provide_legacy_interface:n #1
+ {
% \end{macrocode}
% If the \pkg{expl3} code is run with checking on then assigning or
% using non L3 names such as \cs{@enddocumenthook} with \pkg{expl3}
% functions will trigger warnings so we run this code with
% debugging explicitly suspended.
% \begin{macrocode}
- \debug_suspend:
- \tl_if_exist:cT {@#1hook}
+ \debug_suspend:
+ \tl_if_exist:cT { @#1hook }
% \end{macrocode}
% Of course if the hook exists but is still empty, there is no need
% to add anything under \texttt{legacy} or the current package name.
% \begin{macrocode}
- { \tl_if_empty:cF {@#1hook}
- { \tl_if_empty:NTF \@currname
- { \hook_gput_code:nnv{#1}{legacy}{@#1hook} }
- { \hook_gput_code:nov{#1}{\@currname}{@#1hook} } }
- }
+ {
+ \tl_if_empty:cF { @#1hook }
+ {
+ \@@_gput_code:nxv {#1}
+ { \@@_parse_label_default:Vn \c_novalue_tl { legacy } }
+ { @#1hook }
+ }
+ }
% \end{macrocode}
% We need a global definition in case the declaration is done
% inside a group (which happens below at the end of the file).
@@ -1335,23 +1423,108 @@
% \cs{tl_gset:co} would complain about \cs{@...hook} not starting
% with \cs{g_}.
% \begin{macrocode}
- \tl_gset:co{@#1hook}{\cs:w g_@@_#1_code_tl\cs_end:}
- \debug_resume:
-}
+ \tl_gset:co{@#1hook}{\cs:w g_@@_#1_code_tl\cs_end:}
+ \debug_resume:
+ }
% \end{macrocode}
-% \end{macro}
+% \end{macro}
+%
+% \subsection{Parsing a label}
+%
+% \begin{macro}[EXP]{\@@_parse_label_default:nn,\@@_parse_label_default:Vn}
+% This macro checks if a label was given (not \cs{c_novalue_tl}), and
+% if so, tries to parse the label looking for a leading \verb|.| to
+% replace for \cs{@currname}. Otherwise \cs{@@_currname_or_default:n}
+% is used to pick \cs{@currname} or the fallback value.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_label_default:nn #1 #2
+ {
+ \tl_if_novalue:nTF {#1}
+ { \@@_currname_or_default:n {#2} }
+ { \tl_trim_spaces_apply:nN {#1} \@@_parse_dot_label:nn {#2} }
+ }
+\cs_generate_variant:Nn \@@_parse_label_default:nn { V }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_parse_dot_label:nn}
+% \begin{macro}[EXP]{
+% \@@_parse_dot_label:nw,
+% \@@_parse_dot_label_cleanup:w,
+% \@@_parse_dot_label_aux:nw
+% }
+% Start by checking if the label is empty, which raises an error, and
+% uses the fallback value. If not,
+% split the label at a \verb|./|, if any, and check if no tokens are
+% before the \verb|./|, or if the only character is a \verb|.|.
+% If these requirements are fulfilled, the leading
+% \verb|.| is replaced with \cs{@@_currname_or_default:n}. Otherwise
+% the label is returned unchanged.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_dot_label:nn #1 #2
+ {
+ \tl_if_empty:nTF {#1}
+ {
+ \msg_expandable_error:nnn { hooks } { empty-label } {#2}
+ #2
+ }
+ {
+ \str_if_eq:nnTF {#1} { . }
+ { \@@_currname_or_default:n {#1} }
+ { \@@_parse_dot_label:nw {#2} #1 ./ \s_@@_mark }
+ }
+ }
+\cs_new:Npn \@@_parse_dot_label:nw #1 #2 ./ #3 \s_@@_mark
+ {
+ \tl_if_empty:nTF {#2}
+ { \@@_parse_dot_label_aux:nw {#1} #3 \s_@@_mark }
+ {
+ \tl_if_empty:nTF {#3}
+ {#2}
+ { \@@_parse_dot_label_cleanup:w #2 ./ #3 \s_@@_mark }
+ }
+ }
+\cs_new:Npn \@@_parse_dot_label_cleanup:w #1 ./ \s_@@_mark {#1}
+\cs_new:Npn \@@_parse_dot_label_aux:nw #1 #2 ./ \s_@@_mark
+ { \@@_currname_or_default:n {#1} / #2 }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_currname_or_default:n}
+% Uses \cs{g_@@_hook_curr_name_tl} if it is set, otherwise tries
+% \cs{@currname}. If neither is set, uses the fallback value
+% \verb|#1| (usually \texttt{top-level}).
+% \begin{macrocode}
+\cs_new:Npn \@@_currname_or_default:n #1
+ {
+ \tl_if_empty:NTF \g_@@_hook_curr_name_tl
+ {
+ \tl_if_empty:NTF \@currname
+ {#1}
+ { \@currname }
+ }
+ { \g_@@_hook_curr_name_tl }
+ }
+% \end{macrocode}
+% \end{macro}
-% \begin{macro}{\hook_gput_code:nnn,\hook_gput_code:non,
-% \hook_gput_code:nnv,\hook_gput_code:nov}
-% \begin{macro}{\@@_hook_gput_code_do:nnn}
+
+% \begin{macro}{\hook_gput_code:nnn}
+% \begin{macro}{\@@_gput_code:nnn,\@@_gput_code:nxv,\@@_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}.
% \begin{macrocode}
-\cs_new_protected:Npn \hook_gput_code:nnn #1#2#3
+\cs_new_protected:Npn \hook_gput_code:nnn #1 #2 #3
+ {
+ \exp_args:Nnx \@@_gput_code:nnn {#1}
+ { \@@_parse_label_default:nn {#2} { top-level } } {#3}
+ }
+\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3
{
% \end{macrocode}
% First we check if the hook exists.
@@ -1383,7 +1556,7 @@
{ \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
}
}
-\cs_generate_variant:Nn \hook_gput_code:nnn { non, nnv, nov }
+\cs_generate_variant:Nn \@@_gput_code:nnn { nxv }
% \end{macrocode}
%
% This macro will unconditionally add a chunk of code to the given hook.
@@ -1527,13 +1700,19 @@
% \end{macro}
-% \begin{macro}{\hook_gremove_code:nn,\hook_gremove_code:no}
+% \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.
% \begin{macrocode}
\cs_new_protected:Npn \hook_gremove_code:nn #1 #2
{
+ \exp_args:Nnx \@@_gremove_code:nn {#1}
+ { \@@_parse_label_default:nn {#2} { top-level } }
+ }
+\cs_new_protected:Npn \@@_gremove_code:nn #1 #2
+ {
% \end{macrocode}
% First check that the hook code pool exists. \cs{hook_if_exist:nTF}
% isn't used here because it should be possible to remove code from a
@@ -1554,11 +1733,11 @@
{
% \end{macrocode}
% Check if the label being removed exists in the code pool. If it does,
-% just call \cs{@@_remove_code:nn} to do the removal, otherwise mark it
+% 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
- { \@@_remove_code:nn }
+ { \@@_gremove_code_do:nn }
{ \@@_mark_removal:nn }
{#1} {#2}
}
@@ -1570,12 +1749,11 @@
}
{ \@@_mark_removal:nn {#1} {#2} }
}
-\cs_generate_variant:Nn \hook_gremove_code:nn {no}
% \end{macrocode}
%
-% \begin{macro}{\@@_remove_code:nn}
+% \begin{macro}{\@@_gremove_code_do:nn}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_remove_code:nn #1 #2
+\cs_new_protected:Npn \@@_gremove_code_do:nn #1 #2
{
\prop_gremove:cn { g_@@_#1_code_prop } {#2}
% \end{macrocode}
@@ -1589,6 +1767,7 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
@@ -1733,6 +1912,7 @@
% \subsection{Setting rules for hooks code}
%
% \begin{macro}{\hook_gset_rule:nnnn}
+% \begin{macro}{\@@_gset_rule:nnnn,\@@_gset_rule:nxnx}
%
% \fmi{needs docu correction given new implementation}
%
@@ -1744,6 +1924,15 @@
% \begin{macrocode}
\cs_new_protected:Npn \hook_gset_rule:nnnn #1#2#3#4
{
+ \@@_gset_rule:nxnx {#1}
+ { \@@_parse_label_default:nn {#2} { top-level } } {#3}
+ { \@@_parse_label_default:nn {#4} { top-level } }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_gset_rule:nnnn #1#2#3#4
+ {
% \end{macrocode}
% First we ensure the basic data structure of the hook exists:
% \begin{macrocode}
@@ -1766,8 +1955,10 @@
\debug_resume:
\@@_debug_gset_rule:nnnn {#1} {#2} {#3} {#4} % for debugging
}
+\cs_generate_variant:Nn \@@_gset_rule:nnnn { nxnx }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\@@_rule_before_gset:nnn, \@@_rule_after_gset:nnn,
% \@@_rule_<_gset:nnn, \@@_rule_>_gset:nnn}
@@ -2713,6 +2904,8 @@
LaTeX~found~two~incompatible~labels~in~the~same~hook.~
This~indicates~an~incompatibility~between~packages.
}
+\msg_new:nnn { hooks } { empty-label }
+ { Empty~code~label~\msg_line_context:.~Using~`#1'~instead. }
% \end{macrocode}
%
% \subsection{\LaTeXe{} package interface commands}
@@ -2732,16 +2925,11 @@
%
% \begin{macrocode}
\NewDocumentCommand \AddToHook { m o +m }
- {
- \clist_if_in:NnTF \g_@@_execute_immediately_clist {#1}
- { #3 }
- { \IfValueTF {#2}
- { \hook_gput_code:nnn {#1}{#2}{#3} }
- { \tl_if_empty:NTF \@currname
- { \hook_gput_code:nnn {#1}{top-level}{#3} }
- { \hook_gput_code:non {#1}{\@currname}{#3} } }
- }
-}
+ {
+ \clist_if_in:NnTF \g_@@_execute_immediately_clist {#1}
+ {#3}
+ { \hook_gput_code:nnn {#1} {#2} {#3} }
+ }
% \end{macrocode}
% \end{macro}
@@ -2749,7 +2937,7 @@
%
% \begin{macrocode}
\NewDocumentCommand \AddToHookNext { m +m }
- { \hook_gput_next_code:nn {#1}{#2} }
+ { \hook_gput_next_code:nn {#1} {#2} }
% \end{macrocode}
% \end{macro}
@@ -2758,15 +2946,78 @@
%
% \begin{macrocode}
\NewDocumentCommand \RemoveFromHook { m o }
-{ \IfValueTF {#2}
- { \hook_gremove_code:nn {#1}{#2} }
- { \tl_if_empty:oTF \@currname
- { \hook_gremove_code:nn {#1}{top-level} }
- { \hook_gremove_code:no {#1}{\@currname} } }
-}
+ { \hook_gremove_code:nn {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\DeclareDefaultHookLabel}
+% \begin{macro}{\@@_curr_name_push:n,\@@_curr_name_pop:}
+% 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{DeclareDefaultHookLabel} to change the default label (in which case
+% \cs{@currname} is used, if set).
+%
+% To pull that 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. Since the string \verb|top-level|
+% is hardcoded, here this item of the stack is empty. Also, since
+% we're in an input level, add \verb|lthooks| to the stack as well.
+% This stack should never go empty.
+% \begin{macrocode}
+\seq_gpush:Nn \g_@@_name_stack_seq { }
+\seq_gpush:Nn \g_@@_name_stack_seq { lthooks }
+% \end{macrocode}
+%
+% Two commands keep track of the stack: when a file is input,
+% \cs{@@_curr_name_push:n} pushes an (empty by default) label to the
+% stack:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_curr_name_push:n #1
+ {
+ \seq_gpush:Nn \g_@@_name_stack_seq {#1}
+ \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:NN \g_@@_name_stack_seq \l_@@_return_tl
+ \seq_get:NNTF \g_@@_name_stack_seq \l_@@_return_tl
+ { \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl }
+ { \ERROR_should_not_happen }
+ }
+% \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 \DeclareDefaultHookLabel { m }
+ {
+ \seq_gpop:NN \g_@@_name_stack_seq \l_@@_return_tl
+ \@@_curr_name_push:n {#1}
+ }
+% \begin{macrocode}
+%
+% The push and pop macros are injected in \cs{@pushfilename} and
+% \cs{@popfilename} so that they correctly keep track of the label.s
+% \begin{macrocode}
+% TODO! \pho{Properly integrate in the kernel}
+\tl_gput_left:Nn \@pushfilename { \@@_curr_name_push:n { } }
+\tl_gput_left:Nn \@popfilename { \@@_curr_name_pop: }
+% TODO! \pho{Properly integrate in the kernel}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
%
%
%
@@ -2774,7 +3025,7 @@
% Avoid the overhead of \pkg{xparse} and its protection that we
% don't want here (since the hook should vanish without trace if empty)!
% \begin{macrocode}
-\newcommand \UseHook { \hook_use:n }
+\newcommand \UseHook { \hook_use:n }
% \end{macrocode}
% \end{macro}
%
@@ -3260,12 +3511,15 @@
%
% \subsection{Core hook management code (kernel part)}
%
+% This should run in older formats so we can't use
+% \cs{IfFormatAtLeastTF} right now.
% \begin{macrocode}
-\IfFormatAtLeastTF{2020/10/01}{}
- {\input{lthooks.ltx}
- \input{ltshipout.ltx}
- \input{ltfilehook.ltx}
- }
+\@ifl at t@r\fmtversion{2020/10/01}
+ {}
+ {\input{lthooks.ltx}
+ \input{ltshipout.ltx}
+ \input{ltfilehook.ltx}
+ }
% \end{macrocode}
%
% \subsection{Package options}
More information about the latex3-commits
mailing list.