[latex3-commits] [git/LaTeX3-latex3-latex2e] ltcmdhooks: midnight checkin [WIP] (af5ebc05)
Frank Mittelbach
frank.mittelbach at latex-project.org
Sun Apr 18 00:00:31 CEST 2021
Repository : https://github.com/latex3/latex2e
On branch : ltcmdhooks
Link : https://github.com/latex3/latex2e/commit/af5ebc05b0799acdb6d1543f4ca2d6f59a913a6a
>---------------------------------------------------------------
commit af5ebc05b0799acdb6d1543f4ca2d6f59a913a6a
Author: Frank Mittelbach <frank.mittelbach at latex-project.org>
Date: Sun Apr 18 00:00:31 2021 +0200
midnight checkin [WIP]
>---------------------------------------------------------------
af5ebc05b0799acdb6d1543f4ca2d6f59a913a6a
base/doc/{ltpara-code.tex => ltcmdhooks-code.tex} | 2 +-
base/doc/{ltpara-doc.tex => ltcmdhooks-doc.tex} | 2 +-
base/ltcmdhooks.dtx | 372 +---------------------
base/lthooks.dtx | 237 +++++++++++---
base/update-lthooks-tests.sh | 2 +-
5 files changed, 209 insertions(+), 406 deletions(-)
diff --git a/base/doc/ltpara-code.tex b/base/doc/ltcmdhooks-code.tex
similarity index 77%
copy from base/doc/ltpara-code.tex
copy to base/doc/ltcmdhooks-code.tex
index 2e5beda3..e54dcf10 100644
--- a/base/doc/ltpara-code.tex
+++ b/base/doc/ltcmdhooks-code.tex
@@ -1,4 +1,4 @@
% this will typeset documentation + code
\AtBeginDocument{\AlsoImplementation}
-\input{ltpara.dtx}
+\input{ltcmdhooks.dtx}
diff --git a/base/doc/ltpara-doc.tex b/base/doc/ltcmdhooks-doc.tex
similarity index 87%
copy from base/doc/ltpara-doc.tex
copy to base/doc/ltcmdhooks-doc.tex
index c3892b81..1efae5f2 100644
--- a/base/doc/ltpara-doc.tex
+++ b/base/doc/ltcmdhooks-doc.tex
@@ -3,4 +3,4 @@
\AtBeginDocument{\OnlyDescription
\let\tableofcontents\relax
}
-\input{ltpara.dtx}
+\input{ltcmdhooks.dtx}
diff --git a/base/ltcmdhooks.dtx b/base/ltcmdhooks.dtx
index a02c479b..b2093b84 100644
--- a/base/ltcmdhooks.dtx
+++ b/base/ltcmdhooks.dtx
@@ -13,8 +13,8 @@
%
%%% From File: ltcmdhooks.dtx
%
-\def\ltcmdhooksversion{v0.9c}
-\def\ltcmdhooksdate{2021/04/16}
+\def\ltcmdhooksversion{v0.9d}
+\def\ltcmdhooksdate{2021/04/17}
%
%
%
@@ -53,8 +53,7 @@
%
% \section{Introduction}
%
-% This implements generic hooks for commands.
-%
+% This file implements generic hooks for (arbitrary) commands.
% In theory every command \tn[no-index]{\meta{name}} offers now two
% associated hooks to which code can be added using \tn{AddToHook}
% or \tn{AddToHookNext}.\footnote{In practice this is not supported
@@ -289,150 +288,22 @@
%
% Undefines:
% \begin{macrocode}
-\cs_undefine:N \@@_new:n
-\cs_undefine:N \c_@@_generics_prop
-\cs_undefine:N \@@_try_declaring_generic_hook:wnTF
+%%\cs_undefine:N \@@_new:n
+%%\cs_undefine:N \c_@@_generics_prop
+%%\cs_undefine:N \@@_try_declaring_generic_hook:wnTF
\cs_undefine:N \IfHookExistsTF
-\cs_undefine:N \@@_gput_code:nnn
-\cs_undefine:N \@@_gput_next_code:nn
-\cs_undefine:N \@@_log:nN
+%%\cs_undefine:N \@@_gput_code:nnn
+%%\cs_undefine:N \@@_gput_next_code:nn
+%%\cs_undefine:N \@@_log:nN
% \prg_new_eq_conditional:NNn
% \@@_try_declaring_generic_hook:wn \tex_undefined:D { T, F, TF }
% \end{macrocode}
%
-% \section{On the existence of hooks}
-% \label{sec:existence}
-% \pho{Put this section somewhere in the implementation of lthooks.dtx}
-%
-% A hook may be declared in three stages:
-% \begin{description}[format=\cs]
-% \setlist[itemize]{leftmargin=5cm,format=\cs}
-% \item[@@_declare:n] initializes the basic data structure for the
-% hook so that it may contain code. It creates the hook code pool
-% (\cs[no-index]{g_@@_\meta{hook}_code_prop}) and the |top-level|
-% and |next| token lists. A hook is implicitly declared with
-% \cs{@@_declare:n} when any is added to it. A hook declared only
-% with \cs{@@_declare:n} will not be usable with \cs{hook_use:n}.
-% This state is detected by \cs{@@_if_exist:n} by
-% \cs[no-index]{g_@@_\meta{hook}_code_prop} being defined.
-% \begin{itemize}
-% \item [@@_if_exist:n] returns |true|.
-% \item [@@_if_declared:nTF] returns |false|.
-% \item [@@_if_created:nTF] returns |false|.
-% \item [@@_if_disabled:nTF] returns |false|.
-% \end{itemize}
-% \item[@@_create:n] initializes all hook data structures, as done
-% by \cs{hook_new:n}, except that doing \cs{hook_new:n} on that
-% hook will not result in an error. This is done implicitly by
-% \cs{hook_gput_code:n} when adding code to a generic hook.
-% This state is detected by \cs{@@_if_declared:n} by
-% \cs[no-index]{@@~\meta{hook}} being defined.
-% \begin{itemize}
-% \item [@@_if_exist:n] returns |true|.
-% \item [@@_if_declared:nTF] returns |true|.
-% \item [@@_if_created:nTF] returns |false|.
-% \item [@@_if_disabled:nTF] returns |false|.
-% \end{itemize}
-% \item[hook_new:n] same as \cs{@@_create:n} except it also doesn't
-% allow the hook to be declared again with \cs{hook_new:n}.
-% This state is detected by \cs{@@_if_created:n} by
-% \cs[no-index]{g_@@_\meta{hook}_created_tl} being defined.
-% \begin{itemize}
-% \item [@@_if_exist:n] returns |true|.
-% \item [@@_if_declared:nTF] returns |true|.
-% \item [@@_if_created:nTF] returns |true|.
-% \item [@@_if_disabled:nTF] returns |false|.
-% \end{itemize}
-% \end{description}
-% A hook may additionally be disabled:
-% \begin{description}[format=\cs]
-% \setlist[itemize]{leftmargin=5cm,format=\cs}
-% \item[hook_disable:n] This forces the creation of the
-% \cs[no-index]{g_@@_\meta{hook}_created_tl} so that the hook
-% errors when used with \cs{hook_new:n}, then it undefines
-% \cs[no-index]{@@~\meta{hook}} so that it may not be executed.
-% Since by using the normal hook declaration commands from above
-% we can't get this combination, if a hook has a
-% \cs[no-index]{g_@@_\meta{hook}_created_tl} and not a
-% \cs[no-index]{@@~\meta{hook}} then it is disabled.
-% \cs{@@_if_disabled:n} uses that to check if the hook is
-% disabled.
-% \begin{itemize}
-% \item [@@_if_exist:n] may return |true| or |false|.
-% \item [@@_if_declared:nTF] returns |false|.
-% \item [@@_if_created:nTF] returns |true|.
-% \item [@@_if_disabled:nTF] returns |true|.
-% \end{itemize}
-% \end{description}
-%
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_new:n #1
- {
-% \end{macrocode}
-% We check if the hook was already \emph{explicitly} declared with
-% \cs{hook_new:n}, and if it already exists we complain, otherwise set
-% the \enquote{created} flag for the hook so that it errors next time
-% \cs{hook_new:n} is used.
-% \begin{macrocode}
- \@@_if_created:nTF {#1}
- { \msg_error:nnn { hooks } { exists } {#1} }
- {
- \tl_new:c { g_@@_#1_created_tl }
- \@@_create:n {#1}
- }
- }
-% \end{macrocode}
-%
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_create:n #1
- {
-% \end{macrocode}
-% Now we check if the hook's data structure can be safely created
-% without \pkg{expl3} raising errors, then
-% we add the hook name to the list of all hooks and
-% allocate the necessary data structures for the new hook,
-% otherwise just do nothing.
-% \begin{macrocode}
- \tl_if_exist:cF { @@~#1 }
- {
- \seq_gput_right:Nn \g_@@_all_seq {#1}
-% \end{macrocode}
-% This is only used by the actual code of the current hook, so
-% declare it normally:
-% \begin{macrocode}
- \tl_new:c { @@~#1 }
-% \end{macrocode}
-% Now ensure that the base data structure for the hook exists:
-% \begin{macrocode}
- \@@_declare:n {#1}
-% \end{macrocode}
-% The \cs{g_@@_\meta{hook}_labels_clist} holds the sorted list of
-% labels (once it got sorted). This is used only for debugging.
-% \begin{macrocode}
- \clist_new:c { g_@@_#1_labels_clist }
-% \end{macrocode}
-% Some hooks should reverse the default order of code chunks. To
-% signal this we have a token list which is empty for normal hooks
-% and contains a \verb=-= for reversed hooks.
-% \begin{macrocode}
- \tl_new:c { g_@@_#1_reversed_tl }
-% \end{macrocode}
-% The above is all in L3 convention, but we also provide an
-% interface to legacy \LaTeXe{} hooks of the form \cs{@...hook},
-% e.g., \cs{@begindocumenthook}.
-% there have been a few of them and they have been added to
-% using \cs{g at addto@macro}. If there exists such a macro matching
-% the name of the new hook, i.e.,
-% \verb+\@+\meta{hook-name}\texttt{hook} and it is not empty then
-% we add its contents as a code chunk under the label \texttt{legacy}.
-% \begin{quote}
-% \textbf{Warning: this support will vanish in future releases!}
-% \end{quote}
-%
+
+
+
+
% \begin{macrocode}
- \@@_include_legacy_code_chunk:n {#1}
- }
- }
% \end{macrocode}
%
% Rename \cs{hook_if_exist:nTF} to \cs{@@_if_declared:nTF}
@@ -463,52 +334,7 @@
\cs_new_eq:NN \IfHookExistsTF \@@_if_declared:nTF
% \end{macrocode}
%
-% Add \texttt{cmd} to the list of generic hooks.
% \begin{macrocode}
-\prop_const_from_keyval:Nn \c_@@_generics_prop
- {cmd=,env=,file=,package=,class=,include=}
-\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: }
- {
- \prop_if_in:NnTF \c_@@_generics_prop {#1}
- {
- \@@_if_declared: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
-% declaring the hook.
-%
-% For some commands this will not be possible, in which case
-% \cs{@@_patch_cmd_or_delay:Nnn} will generate an appropriate error
-% message.
-% \begin{macrocode}
- \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
-% message generated elsewhere).
-%
-% Here we use \cs{@@_create:n}, so that a \cs{hook_new:n} is still
-% possible later.
-% \begin{macrocode}
- \@@_create: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:
- }
- { \prg_return_false: }
- }
- }
% \end{macrocode}
%
% \begin{macro}{\hook_disable:n}
@@ -542,72 +368,9 @@
% \end{macro}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3
- {
-% \end{macrocode}
-% First check if the hook was used as a one-time hook:
-% \begin{macrocode}
- \prop_if_in:NnTF \g_@@_execute_immediately_prop {#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.
-% \begin{macrocode}
- \@@_if_declared: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}
-% \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}
- }
-% \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.
-% \begin{macrocode}
- {
- \@@_if_disabled:nTF {#1}
- { \msg_error:nnn { hooks } { hook-disabled } {#1} }
- { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
- }
- }
- }
- }
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_gput_next_code:nn #1 #2
- {
- \@@_if_disabled:nTF {#1}
- { \msg_error:nnn { hooks } { hook-disabled } {#1} }
- {
- \@@_declare:n {#1}
- \hook_if_exist:nTF {#1}
- { \@@_gput_next_do:nn {#1} {#2} }
- { \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
- }
- }
% \end{macrocode}
%
% \begin{macrocode}
@@ -621,115 +384,6 @@
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_log:nN #1 #2
- {
- \@@_preamble_hook:n {#1}
- \@@_log_cmd:x { ^^J ->~The~hook~'#1': }
-% \end{macrocode}
-%
-% \begin{macrocode}
- \@@_if_declared:nF {#1}
- { \@@_log_line:x { The~hook~is~not~declared. } }
- \@@_if_disabled:nT {#1}
- { \@@_log_line:x { The~hook~is~disabled. } }
- \hook_if_empty:nTF {#1}
- { #2 { The~hook~is~empty } }
- {
- \@@_log_line:x { Code~chunks: }
- \prop_if_empty:cTF { g_@@_#1_code_prop }
- { \@@_log_line_indent:x { --- } }
- {
- \prop_map_inline:cn { g_@@_#1_code_prop }
- { \@@_log_line_indent:x { ##1~->~\tl_to_str:n {##2} } }
- }
-% \end{macrocode}
-%
-% If there is code in the |top-level| token list, print it:
-% \begin{macrocode}
- \@@_log_line:x
- {
- Document-level~(top-level)~code
- \@@_if_declared:nT {#1}
- { ~(executed~\@@_if_reversed:nTF {#1} {first} {last} ) } :
- }
- \@@_log_line_indent:x
- {
- \tl_if_empty:cTF { @@_toplevel~#1 }
- { --- }
- { -> ~ \exp_args:Nv \tl_to_str:n { @@_toplevel~#1 } }
- }
-% \end{macrocode}
-%
-% \begin{macrocode}
- \@@_log_line:x { Extra~code~for~next~invocation: }
- \@@_log_line_indent:x
- {
- \tl_if_empty:cTF { @@_next~#1 }
- { --- }
-% \end{macrocode}
-%
-% If the token list is not empty we want to display it but without
-% the first tokens (the code to clear itself) so we call a helper
-% command to get rid of them.
-% \begin{macrocode}
- { ->~ \exp_args:Nv \@@_log_next_code:n { @@_next~#1 } }
- }
-% \end{macrocode}
-%
-% Loop through the rules in a hook and for every rule found, print it.
-% If no rule is there, print |---|. The boolean \cs{l_@@_tmpa_bool}
-% here indicates if the hook has no rules.
-% \begin{macrocode}
- \@@_log_line:x { Rules: }
- \bool_set_true:N \l_@@_tmpa_bool
- \@@_list_rules:nn {#1}
- {
- \bool_set_false:N \l_@@_tmpa_bool
- \@@_log_line_indent:x
- {
- ##2~ with~
- \str_if_eq:nnT {##3} {??} { default~ }
- relation~ ##1
- }
- }
- \bool_if:NT \l_@@_tmpa_bool
- { \@@_log_line_indent:x { --- } }
-% \end{macrocode}
-%
-% When the hook is declared (that is, the sorting algorithm is applied
-% to that hook) and not empty
-% \begin{macrocode}
- \bool_lazy_and:nnTF
- { \@@_if_declared_p:n {#1} }
- { ! \hook_if_empty_p:n {#1} }
- {
- \@@_log_line:x
- {
- Execution~order
- \bool_if:NTF \l_@@_tmpa_bool
- { \@@_if_reversed:nT {#1} { ~(after~reversal) } }
- { ~(after~
- \@@_if_reversed:nT {#1} { reversal~and~ }
- applying~rules)
- } :
- }
- #2 % \tl_show:n
- {
- \@spaces
- \clist_if_empty:cTF { g_@@_#1_labels_clist }
- { --- }
- { \clist_use:cn {g_@@_#1_labels_clist} { ,~ } }
- }
- }
- {
- #2
- {
- Hook~ \@@_if_declared:nTF {#1}
- {code~pool~empty} {not~declared}
- }
- }
- }
- }
% \end{macrocode}
%
% \subsection{Variables}
diff --git a/base/lthooks.dtx b/base/lthooks.dtx
index 42668cfb..52a9d163 100644
--- a/base/lthooks.dtx
+++ b/base/lthooks.dtx
@@ -31,8 +31,8 @@
%%% From File: lthooks.dtx
%
% \begin{macrocode}
-\def\lthooksversion{v1.0j}
-\def\lthooksdate{2021/04/16}
+\def\lthooksversion{v1.0k}
+\def\lthooksdate{2021/04/17}
% \end{macrocode}
%
%<*driver>
@@ -1455,6 +1455,38 @@
% \end{function}
%
%
+% \subsubsection{Generic hooks for commands}
+%
+% Similar to environments there are now (at least in theory) two
+% generic hooks available for any \LaTeX{} command. These are
+% \begin{description}
+% \item[\hook{cmd/\meta{name}/before}]
+%
+% This hook is executed at the very start of the command
+% execution.
+%
+% \item[\hook{cmd/\meta{name}/after}]
+% This hook is executed at the very end of the command body. It is
+% implemented as a reversed hook.
+% \end{description}
+% In practice there are restrictions and especially the
+% \hook{after} hook works only with a subset of commands. Details
+% on restrictions documented in
+% \texttt{ltcmdhooks-doc.pdf} or with code in
+% \texttt{ltcmdhooks-code.pdf}.
+%
+%
+%
+%
+% \subsubsection{Generic hooks provided by file loading operations}
+%
+% There are several hooks added to \LaTeX{}'s
+% process of loading file via its high-level interfaces such as
+% \cs{input}, \cs{include}, \cs{usepackage}, etc. These are documented in
+% \texttt{ltfilehook-doc.pdf} or with code in
+% \texttt{ltfilehook-code.pdf}.
+%
+%
%
% \subsubsection{Hooks provided by \cs{begin}\texttt{\{document\}}}
% \label{sec:begindocument-hooks}
@@ -1630,14 +1662,6 @@
% \texttt{ltshipout-code.pdf}.
%
%
-% \subsubsection{Hooks provided by file loading operations}
-%
-% There are several hooks added to \LaTeX{}'s
-% process of loading file via its high-level interfaces such as
-% \cs{input}, \cs{include}, \cs{usepackage}, etc. These are documented in
-% \texttt{ltfilehook-doc.pdf} or with code in
-% \texttt{ltfilehook-code.pdf}.
-%
%
% \subsubsection{Hooks provided in NFSS commands}
%
@@ -1999,25 +2023,44 @@
%
%
%
-% \begin{macro}{\hook_new:n}
+% \begin{macro}{\hook_new:n,\@@_new:n,\@@_create:n}
% The \cs{hook_new:n} declaration declare a new hook and expects
% the hook \meta{name} as its argument, e.g.,
% \hook{begindocument}.
% \begin{macrocode}
\cs_new_protected:Npn \hook_new:n #1
{ \@@_normalize_hook_args:Nn \@@_new:n {#1} }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_new:n #1
{
% \end{macrocode}
-% We check for one of the internal data structures and if it
-% already exists we complain.
+% We check if the hook was already \emph{explicitly} declared with
+% \cs{hook_new:n}, and if it already exists we complain, otherwise set
+% the \enquote{created} flag for the hook so that it errors next time
+% \cs{hook_new:n} is used.
% \begin{macrocode}
- \hook_if_exist:nTF {#1}
+ \@@_if_created:nTF {#1}
{ \msg_error:nnn { hooks } { exists } {#1} }
+ {
+ \tl_new:c { g_@@_#1_created_tl }
+ \@@_create:n {#1}
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_create:n #1
+ {
% \end{macrocode}
-% Otherwise we add the hook name to the list of all hooks and
-% allocate the necessary data structures for the new hook.
+% Now we check if the hook's data structure can be safely created
+% without \pkg{expl3} raising errors, then
+% we add the hook name to the list of all hooks and
+% allocate the necessary data structures for the new hook,
+% otherwise just do nothing.
% \begin{macrocode}
+ \tl_if_exist:cF { @@~#1 }
{
\seq_gput_right:Nn \g_@@_all_seq {#1}
% \end{macrocode}
@@ -2033,7 +2076,7 @@
% The \cs{g_@@_\meta{hook}_labels_clist} holds the sorted list of
% labels (once it got sorted). This is used only for debugging.
% \begin{macrocode}
- \clist_new:c {g_@@_#1_labels_clist}
+ \clist_new:c { g_@@_#1_labels_clist }
% \end{macrocode}
% Some hooks should reverse the default order of code chunks. To
% signal this we have a token list which is empty for normal hooks
@@ -2055,7 +2098,7 @@
%
% \begin{macrocode}
\@@_include_legacy_code_chunk:n {#1}
- }
+ }
}
% \end{macrocode}
% \end{macro}
@@ -2152,6 +2195,74 @@
% \end{macro}
%
%
+% \subsection{On the existence of hooks}
+% \label{sec:existence}
+%
+% A hook may be declared in three stages:
+% \begin{description}[format=\cs]
+% \setlist[itemize]{leftmargin=5cm,format=\cs}
+% \item[@@_declare:n] initializes the basic data structure for the
+% hook so that it may contain code. It creates the hook code pool
+% (\cs[no-index]{g_@@_\meta{hook}_code_prop}) and the |top-level|
+% and |next| token lists. A hook is implicitly declared with
+% \cs{@@_declare:n} when any is added to it. A hook declared only
+% with \cs{@@_declare:n} will not be usable with \cs{hook_use:n}.
+% This state is detected by \cs{@@_if_exist:n} by
+% \cs[no-index]{g_@@_\meta{hook}_code_prop} being defined.
+% \begin{itemize}
+% \item [@@_if_exist:n] returns |true|.
+% \item [@@_if_declared:nTF] returns |false|.
+% \item [@@_if_created:nTF] returns |false|.
+% \item [@@_if_disabled:nTF] returns |false|.
+% \end{itemize}
+% \item[@@_create:n] initializes all hook data structures, as done
+% by \cs{hook_new:n}, except that doing \cs{hook_new:n} on that
+% hook will not result in an error. This is done implicitly by
+% \cs{hook_gput_code:n} when adding code to a generic hook.
+% This state is detected by \cs{@@_if_declared:n} by
+% \cs[no-index]{@@~\meta{hook}} being defined.
+% \begin{itemize}
+% \item [@@_if_exist:n] returns |true|.
+% \item [@@_if_declared:nTF] returns |true|.
+% \item [@@_if_created:nTF] returns |false|.
+% \item [@@_if_disabled:nTF] returns |false|.
+% \end{itemize}
+% \item[hook_new:n] same as \cs{@@_create:n} except it also doesn't
+% allow the hook to be declared again with \cs{hook_new:n}.
+% This state is detected by \cs{@@_if_created:n} by
+% \cs[no-index]{g_@@_\meta{hook}_created_tl} being defined.
+% \begin{itemize}
+% \item [@@_if_exist:n] returns |true|.
+% \item [@@_if_declared:nTF] returns |true|.
+% \item [@@_if_created:nTF] returns |true|.
+% \item [@@_if_disabled:nTF] returns |false|.
+% \end{itemize}
+% \end{description}
+% A hook may additionally be disabled:
+% \begin{description}[format=\cs]
+% \setlist[itemize]{leftmargin=5cm,format=\cs}
+% \item[hook_disable:n] This forces the creation of the
+% \cs[no-index]{g_@@_\meta{hook}_created_tl} so that the hook
+% errors when used with \cs{hook_new:n}, then it undefines
+% \cs[no-index]{@@~\meta{hook}} so that it may not be executed.
+% Since by using the normal hook declaration commands from above
+% we can't get this combination, if a hook has a
+% \cs[no-index]{g_@@_\meta{hook}_created_tl} and not a
+% \cs[no-index]{@@~\meta{hook}} then it is disabled.
+% \cs{@@_if_disabled:n} uses that to check if the hook is
+% disabled.
+% \begin{itemize}
+% \item [@@_if_exist:n] may return |true| or |false|.
+% \item [@@_if_declared:nTF] returns |false|.
+% \item [@@_if_created:nTF] returns |true|.
+% \item [@@_if_disabled:nTF] returns |true|.
+% \end{itemize}
+% \end{description}
+%
+%
+%
+%
+%
%
% \subsection{Parsing a label}
%
@@ -2313,6 +2424,9 @@
% \begin{macrocode}
\cs_new_protected:Npn \hook_gput_code:nnn #1 #2
{ \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3
{
% \end{macrocode}
@@ -2336,7 +2450,7 @@
% If no removal is queued, we are free to add. Start by checking if
% the hook exists.
% \begin{macrocode}
- \hook_if_exist:nTF {#1}
+ \@@_if_declared: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}=
@@ -2357,10 +2471,17 @@
% declare it as a generic hook, if its name matches one of the valid
% patterns.
% \begin{macrocode}
- { \@@_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}
%
@@ -2475,12 +2596,18 @@
}
{ \@@_try_declaring_generic_hook_split:nNNnn {#1} }
}
+% \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}
}
+% \end{macrocode}
+%
+% \begin{macrocode}
\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
#1 / #2 / #3 / #4 \scan_stop: #5 { TF }
{
@@ -2489,22 +2616,35 @@
{
\prop_if_in:NnTF \c_@@_generics_prop {#1}
{
- \hook_if_exist:nF {#5} { \hook_new:n {#5} }
+ \@@_if_declared: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
+% declaring the hook.
+%
+% For some commands this will not be possible, in which case
+% \cs{@@_patch_cmd_or_delay:Nnn} will generate an appropriate error
+% message.
+% \begin{macrocode}
+ \str_if_eq:nnT {#1} { cmd }
+ { \@@_try_put_cmd_hook:n {#5} }
% \end{macrocode}
-% After having declared the hook we check the second component (for
-% file hooks) or the third component for environment hooks) and
-% if it is on the list of components for which we should have declared
-% a reversed hook we alter the hook data structure accordingly.
+%
+% Declare the hook always even if it can't really be used (error
+% message generated elsewhere).
+%
+% Here we use \cs{@@_create:n}, so that a \cs{hook_new:n} is still
+% possible later.
% \begin{macrocode}
+ \@@_create: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 } { - } }
}
-% \end{macrocode}
-% Now that we know that the hook is declared we can add the code to it.
-% \begin{macrocode}
\prg_return_true:
}
{ \prg_return_false: }
@@ -2588,14 +2728,16 @@
% Property list holding the generic names. 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.
% \item[\texttt{env}]
% The generic hooks used in \cs{begin} and \cs{end}.
-% \item[\texttt{file}]
+% \item[\texttt{file}, \texttt{package}, \texttt{class}, \texttt{include}]
% The generic hooks used when loading a file
% \end{description}
% \begin{macrocode}
\prop_const_from_keyval:Nn \c_@@_generics_prop
- {env=,file=,package=,class=,include=}
+ {cmd=,env=,file=,package=,class=,include=}
% \end{macrocode}
% \end{macro}
%
@@ -3567,6 +3709,9 @@
{ \@@_log_cmd:x { >~#1 } }
\cs_new_protected:Npn \@@_log_line_indent:x #1
{ \@@_log_cmd:x { >~\@spaces #1 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_log:nN #1 #2
{
\@@_preamble_hook:n {#1}
@@ -3574,8 +3719,10 @@
% \end{macrocode}
%
% \begin{macrocode}
- \hook_if_exist:nF {#1}
- { \@@_log_line:x { is~not~declared! } }
+ \@@_if_declared:nF {#1}
+ { \@@_log_line:x { The~hook~is~not~declared. } }
+ \@@_if_disabled:nT {#1}
+ { \@@_log_line:x { The~hook~is~disabled. } }
\hook_if_empty:nTF {#1}
{ #2 { The~hook~is~empty } }
{
@@ -3593,7 +3740,7 @@
\@@_log_line:x
{
Document-level~(top-level)~code
- \hook_if_exist:nT {#1}
+ \@@_if_declared:nT {#1}
{ ~(executed~\@@_if_reversed:nTF {#1} {first} {last} ) } :
}
\@@_log_line_indent:x
@@ -3644,7 +3791,7 @@
% to that hook) and not empty
% \begin{macrocode}
\bool_lazy_and:nnTF
- { \hook_if_exist_p:n {#1} }
+ { \@@_if_declared_p:n {#1} }
{ ! \hook_if_empty_p:n {#1} }
{
\@@_log_line:x
@@ -3668,7 +3815,7 @@
{
#2
{
- Hook~ \hook_if_exist:nTF {#1}
+ Hook~ \@@_if_declared:nTF {#1}
{code~pool~empty} {not~declared}
}
}
@@ -3773,17 +3920,19 @@
% \begin{macrocode}
\cs_new_protected:Npn \hook_gput_next_code:nn #1
{ \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_next_code:nn #1 #2
{
- \@@_declare:n {#1}
- \hook_if_exist:nTF {#1}
- { \@@_gput_next_do:nn {#1} {#2} }
- { \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
- }
-\cs_new_protected:Npn \@@_gput_next_do:nn #1
- {
- \exp_args:Nc \@@_gput_next_do:Nnn
- { @@_next~#1 } {#1}
+ \@@_if_disabled:nTF {#1}
+ { \msg_error:nnn { hooks } { hook-disabled } {#1} }
+ {
+ \@@_declare:n {#1}
+ \hook_if_exist:nTF {#1}
+ { \@@_gput_next_do:nn {#1} {#2} }
+ { \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
+ }
}
% \end{macrocode}
% First check if the ``next code'' token list is empty: if so we need
diff --git a/base/update-lthooks-tests.sh b/base/update-lthooks-tests.sh
index 4de8f625..0579ea6c 100644
--- a/base/update-lthooks-tests.sh
+++ b/base/update-lthooks-tests.sh
@@ -10,7 +10,7 @@ l3build save -cconfig-lthooks \
ltcmdhooks-008 \
ltcmdhooks-009
-
+exit
l3build save -cconfig-lthooks2 \
lthooks2-002 \
More information about the latex3-commits
mailing list.