Skip to content

Commit

Permalink
Merge pull request #1020 from latex3/hook-args
Browse files Browse the repository at this point in the history
Hooks with arguments
  • Loading branch information
PhelypeOleinik committed Apr 16, 2023
2 parents e62949b + 9833018 commit 11b9dde
Show file tree
Hide file tree
Showing 50 changed files with 6,756 additions and 378 deletions.
11 changes: 10 additions & 1 deletion base/changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ are not part of the distribution.

* cmfonts.fdd: add missing substitution for U/cmtt/bx/sl gh/1037

2023-04-13 Phelype Oleinik <phelype.oleinik@latex-project.org>
2023-04-12 Phelype Oleinik <phelype.oleinik@latex-project.org>

* ltcmd.dtx (subsection{Grabbing arguments}):
Set \tex_endlinechar:D earlier to correct parsing of newlines in
Expand All @@ -30,6 +30,15 @@ are not part of the distribution.

* ltfilehook.dtx: allow par as a filename. (gh/942)

2023-04-06 Phelype Oleinik <phelype.oleinik@latex-project.org>

* lthooks.dtx, ltcmdhooks.dtx:
Add support for providing and using arguments in hooks:
- Modify hook data structures to allow access to arguments;
- Add commands to declare hooks with arguments;
- Add commands to add code that references hook arguments;
- Add commands to use hooks with arguments.

2023-04-01 David Carlisle <David.Carlisle@latex-project.org>

* ltfssbas.dtx: locally reset frozen mathversions when the math
Expand Down
58 changes: 57 additions & 1 deletion base/doc/ltnews37.tex
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ \subsection{Displaying the exact release dates for \LaTeX{}}
commands and in the past that was not that easy to find. You could have
looked in the the file \file{changes.txt}, but that is hidden somewhere
in your installation and if you try
\verb*/texdoc -l changes.txt/ you get more than thirty results and the
\verb*/texdoc -l changes.txt/ you get more than thirty results and the %*
right file is by no means the first.

Yukai Chou (\textsf{@muzimuzhi}) kindly provided a patch for this, so that we now have
Expand Down Expand Up @@ -247,6 +247,58 @@ \subsection{Displaying the exact release dates for \LaTeX{}}

\section{New or improved commands}

\subsection{Extending hooks to take arguments}

Hooks have always been containers for code whose outcome was entirely
dependent on the contents of the hook alone. If any type of contextual
information had to be passed to the hook, it had to be done by setting
some variable before the hook so that the code in the hook could use
that. But this is somewhat hard to keep track of, clumsy to implement,
and it required the programmer to have some kind of \enquote{hook before
the hook} to do that setup.

To make things a bit easier, \pkg{lthooks} was enhanced to support hooks
with arguments. Hooks can now be declared and used with arguments, then
the code added to these hooks can reference the hook's arguments using
\verb|#1|, \verb|#2|, etc., so now hooks can behave more like macros
than like \emph{token lists} (using \pkg{expl3} terminology). Regular
argument-less hooks continue to work exactly like they did before: this
extension is completely compatible with older documents and packages.

\AddToHook{cmd/verbatim@font/after}[hack]{\small}
To declare a hook with arguments, use
\begin{verbatim}
\NewHookWithArguments {<hook>} {<num args>}
\end{verbatim}
then, similarly, to use the code in the hook (supposing a hook declared
with 2 arguments), write
\begin{verbatim}
\UseHookWithArguments {<hook>} {2} {<arg 1>} {<arg 2>}
\end{verbatim}

Or, if you want to add some code to a hook that takes arguments, write
\begin{verbatim}
\AddToHookWithArguments {<hook>} [<label>] {<code>}
\end{verbatim}
exactly like you would for regular hooks, except that the \meta{code}
can use the arguments by referencing \verb|#1|, \verb|#2|, etc. In this
case, if you want to add an actual parameter token (\verb|#|) to the
\meta{code}, you have to double it, as usual.
\RemoveFromHook{cmd/verbatim@font/after}[hack]

Additionally, if you want to add \enquote{regular} code to a hook with
arguments, you can still use \cs{AddToHook} --- in that case \verb|#|
tokens are \emph{not} doubled. This means that a package author can
decide to add arguments to an existing hook without worrying about
compatibility: \cs{AddToHook} will do the right thing and will not
mistakenly reference the newly added arguments.

The commands \cs{NewReversedHookWithArguments}, \cs
{NewMirroredHookPairWithArguments}, \cs
{AddToHookNextWithArguments}, \cs{UseOneTimeHookWithArguments}, and
the \pkg{expl3} conterparts of the commands discussed in this section
were also added. The complete documentation can be found in the
\pkg{lthooks} documentation \cite{37:lthooks-doc}.


\subsection{Providing copy and show functions for environments}
Expand Down Expand Up @@ -589,6 +641,10 @@ \subsection{\pkg{multicol}: Fix handling of nested environments}
\emph{The \texttt{\upshape ltshipout} documentation}.\\
Run \texttt{texdoc} \texttt{ltshipout-doc} to view.
\bibitem{37:lthooks-doc} Frank Mittelbach, Phelype Oleinik, \LaTeX{}~Project~Team:
\emph{\LaTeX's hook management}.\\
Run \texttt{texdoc} \texttt{lthooks-doc} to view.
%\bibitem{37:blueprint} Frank Mittelbach and Chris Rowley:
% \emph{\LaTeX{} Tagged PDF \Dash A blueprint for a large project}.\\
% \url{https://latex-project.org/publications/indexbyyear/2020/}
Expand Down
47 changes: 29 additions & 18 deletions base/ltcmdhooks.dtx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
%
%%% From File: ltcmdhooks.dtx
%
\def\ltcmdhooksversion{v1.0f}
\def\ltcmdhooksdate{2021/10/20}
\def\ltcmdhooksversion{v1.0g}
\def\ltcmdhooksdate{2023/04/06}
%
%
%
Expand Down Expand Up @@ -367,10 +367,13 @@
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c_@@_hash_tl}
% A constant token list that contains two parameter tokens.
% \begin{macro}{\c_@@_hash_tl,\c_@@_hashes_tl}
% Two constant token lists that contain one and two parameter tokens.
% \changes{v1.0g}{2023/04/06}
% {Rename to \cs{c_@@_hashes_tl} and add \cs{c_@@_hash_tl} (hook-args).}
% \begin{macrocode}
\tl_const:Nn \c_@@_hash_tl { # # }
\tl_const:Nn \c_@@_hash_tl { # }
\tl_const:Nn \c_@@_hashes_tl { # # }
% \end{macrocode}
% \end{macro}
%
Expand Down Expand Up @@ -780,14 +783,14 @@
% should be identical to the \meta{parameter text} used when
% originally defining that macro.
% \item[\cs{l_@@_replace_text_tl}] will contain braced pairs of
% \cs{c_@@_hash_tl}\meta{num} to feed to the macro when expanded.
% \cs{c_@@_hashes_tl}\meta{num} to feed to the macro when expanded.
% This token list as well as the previous will have the first item
% surrounded by |[|\ldots|]| in the case of an optional argument.
% \end{description}
%
% The use of \cs{c_@@_hash_tl} here is to differentiate actual
% The use of \cs{c_@@_hashes_tl} here is to differentiate actual
% parameters in the macro from parameter tokens in the original
% definition of the macro. Later on, \cs{c_@@_hash_tl} is either
% definition of the macro. Later on, \cs{c_@@_hashes_tl} is either
% replaced by actual parameter tokens, or expanded into them.
% \begin{macrocode}
\int_compare:nNnTF { \l_@@_patch_num_args_int } > { \c_zero_int }
Expand All @@ -796,7 +799,7 @@
% We'll first check if the command has any parameter token in its
% definition (feeding it empty arguments), and set \cs{@@_exp_not:n}
% accordingly. \cs{@@_exp_not:n} will be used later to either leave
% \cs{c_@@_hash_tl} or expand it, and also to remember the result of
% \cs{c_@@_hashes_tl} or expand it, and also to remember the result of
% \cs{@@_if_has_hash:nTF} to avoid testing twice (the test can be
% rather slow).
% \begin{macrocode}
Expand All @@ -815,20 +818,22 @@
% \end{macrocode}
% Here we'll conditionally add |[|\ldots|]| around the first
% parameter:
% \changes{v1.0g}{2023/04/06}
% {Rename to \cs{c_@@_hashes_tl} (hook-args).}
% \begin{macrocode}
\bool_if:NTF #1
{ \@@_tmp:w \tl_set:Nx { [ \c_@@_hash_tl 1 ] } }
{ \@@_tmp:w \tl_set:Nx { { \c_@@_hash_tl 1 } } }
{ \@@_tmp:w \tl_set:Nx { [ \c_@@_hashes_tl 1 ] } }
{ \@@_tmp:w \tl_set:Nx { { \c_@@_hashes_tl 1 } } }
% \end{macrocode}
% Then, for every parameter from the second, just add it normally:
% \begin{macrocode}
\int_step_inline:nnn { 2 } { \l_@@_patch_num_args_int }
{ \@@_tmp:w \tl_put_right:Nx { { \c_@@_hash_tl ##1 } } }
{ \@@_tmp:w \tl_put_right:Nx { { \c_@@_hashes_tl ##1 } } }
% \end{macrocode}
% Now, if the command has any parameter token in its definition
% (then \cs{@@_exp_not:n} is \cs{exp_not:n}), call
% \cs{@@_double_hashes:n} to double them, and replace every
% \cs{c_@@_hash_tl} by |#|:
% \cs{c_@@_hashes_tl} by |#|:
% \begin{macrocode}
\tl_set:Nx \l_@@_replace_text_tl
{ \exp_not:N #2 \exp_not:V \l_@@_replace_text_tl }
Expand Down Expand Up @@ -974,7 +979,7 @@
% }
% \cs{@@_double_hashes:n} loops through the token list |#1| and
% duplicates any catcode~6 token, and expands tokens \cs{ifx}-equal to
% \cs{c_@@_hash_tl}, and leaves all other tokens \cs{notexpanded} with
% \cs{c_@@_hashes_tl}, and leaves all other tokens \cs{notexpanded} with
% \cs{exp_not:N}. Unfortunately pairs of explicit catcode~1 and
% catcode~2 character tokens are normalised to |{|$_1$ and |}|$_1$
% because it's not feasible to expandably detect the character code
Expand All @@ -1001,26 +1006,32 @@
% \end{macrocode}
%
% \cs{@@_double_hashes_output:N} checks for the end of the token list,
% then checks if the token is \cs{c_@@_hash_tl}, and if so just leaves
% then checks if the token is \cs{c_@@_hashes_tl}, and if so just leaves
% it.
% \changes{v1.0g}{2023/04/06}
% {Add case for \cs{c_@@_hashes_tl} (hook-args).}
% \begin{macrocode}
\cs_new:Npn \@@_double_hashes_output:N #1
{
\if_meaning:w \q_@@_recursion_tail #1
\@@_double_hashes_stop:w
\fi:
\if_meaning:w \c_@@_hash_tl #1
\if:w ?
\if_meaning:w \c_@@_hash_tl #1 ! \fi:
\if_meaning:w \c_@@_hashes_tl #1 ! \fi:
?
\else:
% \end{macrocode}
% (this \cs{use_i:nnnn} uses \cs{fi:} and consumes \cs{use:n}, the
% whole \cs{if_catcode:w} block, and the \cs{exp_not:N}, leaving just
% |#1| which is \cs{c_@@_hash_tl}.)
% |#1| which is \cs{c_@@_hashes_tl}.)
% \begin{macrocode}
\use_i:nnnn
\fi:
\use:n
{
% \end{macrocode}
% If |#1| is not \cs{c_@@_hash_tl}, then check if its catcode is~6,
% If |#1| is not \cs{c_@@_hashes_tl}, then check if its catcode is~6,
% and if so, leave it doubled in \cs{exp_not:n} and consume the
% following |\exp_not:N #1|.
% \begin{macrocode}
Expand Down

0 comments on commit 11b9dde

Please sign in to comment.