summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/base
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-11-12 23:08:46 +0000
committerKarl Berry <karl@freefriends.org>2021-11-12 23:08:46 +0000
commite80240b5e5bfb83d84a9e6d81e31b0bfb82d637c (patch)
treeb76f4a81a066673810d3b9ee777926d848f414f0 /Master/texmf-dist/source/latex/base
parent0ff2ba12c9b350c0546c2256e398168d325d234a (diff)
2e (12nov21)
git-svn-id: svn://tug.org/texlive/trunk@61041 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/base')
-rw-r--r--Master/texmf-dist/source/latex/base/classes.dtx28
-rw-r--r--Master/texmf-dist/source/latex/base/doc.dtx11
-rw-r--r--Master/texmf-dist/source/latex/base/ltboxes.dtx25
-rw-r--r--Master/texmf-dist/source/latex/base/ltclass.dtx159
-rw-r--r--Master/texmf-dist/source/latex/base/ltcmd.dtx1015
-rw-r--r--Master/texmf-dist/source/latex/base/ltcmdhooks.dtx456
-rw-r--r--Master/texmf-dist/source/latex/base/ltcounts.dtx132
-rw-r--r--Master/texmf-dist/source/latex/base/ltdefns.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/lterror.dtx111
-rw-r--r--Master/texmf-dist/source/latex/base/ltexpl.dtx2
-rw-r--r--Master/texmf-dist/source/latex/base/ltfilehook.dtx164
-rw-r--r--Master/texmf-dist/source/latex/base/ltfiles.dtx38
-rw-r--r--Master/texmf-dist/source/latex/base/ltfinal.dtx41
-rw-r--r--Master/texmf-dist/source/latex/base/ltfloat.dtx27
-rw-r--r--Master/texmf-dist/source/latex/base/ltfntcmd.dtx5
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssbas.dtx5
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssdcl.dtx255
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssini.dtx383
-rw-r--r--Master/texmf-dist/source/latex/base/ltfsstrc.dtx2
-rw-r--r--Master/texmf-dist/source/latex/base/lthooks.dtx1909
-rw-r--r--Master/texmf-dist/source/latex/base/ltluatex.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/ltmath.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/ltmiscen.dtx5
-rw-r--r--Master/texmf-dist/source/latex/base/ltoutenc.dtx15
-rw-r--r--Master/texmf-dist/source/latex/base/ltoutput.dtx78
-rw-r--r--Master/texmf-dist/source/latex/base/ltpara.dtx253
-rw-r--r--Master/texmf-dist/source/latex/base/ltplain.dtx20
-rw-r--r--Master/texmf-dist/source/latex/base/ltsect.dtx42
-rw-r--r--Master/texmf-dist/source/latex/base/ltshipout.dtx18
-rw-r--r--Master/texmf-dist/source/latex/base/ltvers.dtx16
-rw-r--r--Master/texmf-dist/source/latex/base/makeindx.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/preload.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/slides.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/tulm.fdd9
-rw-r--r--Master/texmf-dist/source/latex/base/utf8ienc.dtx36
35 files changed, 3910 insertions, 1384 deletions
diff --git a/Master/texmf-dist/source/latex/base/classes.dtx b/Master/texmf-dist/source/latex/base/classes.dtx
index ffe04c620fa..a13053b871a 100644
--- a/Master/texmf-dist/source/latex/base/classes.dtx
+++ b/Master/texmf-dist/source/latex/base/classes.dtx
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{classes.drv}
%</driver>
- [2021/02/12 v1.4n
+ [2021/10/04 v1.4n
%<article|report|book> Standard LaTeX document class]
%<10pt|11pt|12pt> Standard LaTeX file (size option)]
% \end{macrocode}
@@ -221,9 +221,9 @@
% file has version number \fileversion, last revised \filedate.}}
%
% \author{%
-% Copyright (C) 1992 by Leslie Lamport and
-% Copyright (C) 1994-2020 by Frank Mittelbach and Johannes Braams and
-% LaTeX Project Team
+% Copyright (C) 1992 by Leslie Lamport \and
+% Copyright (C) 1994-2021 by Frank Mittelbach, \and Johannes Braams and
+% the \LaTeX\ Project Team
% }
% \date{\filedate}
% \MaintainedByLaTeXTeam{latex}
@@ -1622,7 +1622,7 @@
% \label{sec:classes:pagestyle}
%
% The pagestyles \pstyle{empty} and \pstyle{plain} are defined in
-% \file{latex.dtx}.
+% the \LaTeX{} format.
%
% \begin{macro}{\ps@headings}
% The definition of the page style \pstyle{headings} has to be
@@ -1771,7 +1771,7 @@
% \begin{macro}{\title}
% \begin{macro}{\author}
% \begin{macro}{\date}
-% These three macros are provided by \file{latex.dtx} to provide
+% These three macros are provided by the \LaTeX{} format to provide
% information about the title, author(s) and date of the document.
% The information is stored away in internal control sequences.
% It is the task of the |\maketitle| command to use the
@@ -2056,7 +2056,7 @@
% Default initializations of |\...mark| commands. These commands
% are used in the definition of the page styles (see
% section~\ref{sec:classes:pagestyle}) Most of them are already defined by
-% \file{latex.dtx}, so they are only shown here.
+% the \LaTeX{} format, so they are only shown here.
%
% \begin{macrocode}
%<!article>\newcommand*\chaptermark[1]{}
@@ -2891,7 +2891,7 @@
% \begin{macro}{\theenumii}
% \begin{macro}{\theenumiii}
% \begin{macro}{\theenumiv}
-% The counters are already defined in \file{latex.dtx}, but their
+% The counters are already defined in the \LaTeX{} format, but their
% representation is changed here.
%
% \begin{macrocode}
@@ -2990,7 +2990,7 @@
%
% \begin{environment}{description}
% The description environment is defined here -- while the itemize
-% and enumerate environments are defined in \file{latex.dtx}.
+% and enumerate environments are defined in the \LaTeX{} format.
%
% \begin{macrocode}
\newenvironment{description}
@@ -3123,7 +3123,7 @@
% \subsubsection{Theorem}
%
% This document class does not define it's own theorem environments,
-% the defaults, supplied by \file{latex.dtx} are available.
+% the defaults, supplied by the \LaTeX{} format are available.
%
% \subsubsection{Titlepage}
%
@@ -3365,7 +3365,7 @@
%
% \subsection{Floating objects}
%
-% The file \file{latex.dtx} only defines a number of tools with
+% The \LaTeX{} format only defines a number of tools with
% which floating objects can be defined. This is done in the
% document class. It needs to define the following macros for each
% floating object of type \texttt{TYPE} (e.g., \texttt{TYPE} =
@@ -3402,7 +3402,7 @@
%
% The actual environment that implements a floating object such as
% a figure is defined using the macros |\@float| and |\end@float|,
-% which are defined in \file{latex.dtx}.
+% which are defined in the \LaTeX{} format.
%
% An environment that implements a single-column floating object is
% started with |\@float{|\texttt{TYPE}|}[|\meta{placement}|]| of type
@@ -4194,7 +4194,7 @@
%
% \begin{macro}{\@biblabel}
% The label for a |\bibitem[...]| command is produced by this
-% macro. The default from \file{latex.dtx} is used.
+% macro. The default from the \LaTeX{} format is used.
% \begin{macrocode}
% \renewcommand*{\@biblabel}[1]{[#1]\hfill}
% \end{macrocode}
@@ -4202,7 +4202,7 @@
%
% \begin{macro}{\@cite}
% The output of the |\cite| command is produced by this macro. The
-% default from \file{latex.dtx} is used.
+% default from the \LaTeX{} format is used.
% \begin{macrocode}
% \renewcommand*{\@cite}[1]{[#1]}
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/doc.dtx b/Master/texmf-dist/source/latex/base/doc.dtx
index fb3412f21f4..41bc0733155 100644
--- a/Master/texmf-dist/source/latex/base/doc.dtx
+++ b/Master/texmf-dist/source/latex/base/doc.dtx
@@ -35,7 +35,7 @@
%<+package|shortvrb>\NeedsTeXFormat{LaTeX2e}[1994/12/01]
%<+package> \ProvidesPackage{doc}
%<+shortvrb>\ProvidesPackage{shortvrb}
-%<+package|shortvrb> [2021/05/28 v2.1n
+%<+package|shortvrb> [2021/10/04 v2.1n
%<+package|shortvrb> Standard LaTeX documentation package (FMi)]
%\catcode`\<=12
%
@@ -885,7 +885,7 @@
% We provide macros for logos such as \Web, \AmSTeX, \BibTeX,
% \SliTeX{} and \PlainTeX. Just type |\Web|, |\AmSTeX|,
% |\BibTeX|, |\SliTeX| or |\PlainTeX|, respectively.
-% \LaTeX{} and \TeX{} are already defined in \texttt{latex.tex}.
+% \LaTeX{} and \TeX{} are already defined in the \LaTeX{} format.
%
% \DescribeMacro\meta
% Another useful macro is |\meta| which has one argument and
@@ -938,7 +938,8 @@
% argument and produces a verbatim listing of the file, indexing every
% command as it goes along. This might be handy, if you want to learn
% something about macros without enough documentation. I used this
-% feature to cross-reference \texttt{latex.tex} getting a verbatim
+% feature to cross-reference \texttt{latex.tex} (these days
+% called \texttt{latex.ltx}) getting a verbatim
% copy with about 15 pages index.\footnote{It took quite a long time
% and the resulting \texttt{.idx} file was longer than the
% \texttt{.dvi} file. Actually too long to be handled by the
@@ -2031,7 +2032,7 @@
% \begin{macro}{\@verbatim}
% Additionally we redefine the |\@verbatim| macro so that it
% suppresses |%| characters at the beginning of the line. The
-% first lines are copied literally from \texttt{latex.tex}.
+% first lines are copied literally from the \LaTeX{} format.
% \changes{v1.7i}{1992/07/12}{Added \cs{@@par} to clear possible
% \cs{parshape}.}
% \begin{macrocode}
@@ -2055,7 +2056,7 @@
% \begin{macrocode}
\check@percent}%
% \end{macrocode}
-% The rest is again copied literally from \texttt{latex.tex} (less
+% The rest is again copied literally from the \LaTeX{} format (less
% "\tt").
% \changes{v1.7a}{1992/02/26}{Removed redundant \cs{tt}.}
% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX verbatim,
diff --git a/Master/texmf-dist/source/latex/base/ltboxes.dtx b/Master/texmf-dist/source/latex/base/ltboxes.dtx
index 8499d3ab8b9..92d9228a8af 100644
--- a/Master/texmf-dist/source/latex/base/ltboxes.dtx
+++ b/Master/texmf-dist/source/latex/base/ltboxes.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltboxes.dtx}
- [2021/02/10 v1.4b LaTeX Kernel (Box Commands)]
+ [2021/10/14 v1.4c LaTeX Kernel (Box Commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltboxes.dtx}
@@ -1137,10 +1137,12 @@
% {Color groups restored here.}
% \changes{v1.4b}{2021/02/10}
% {Explicitly run \cs{par} in support for paragraph tagging}
+% \changes{v1.4c}{2021/10/14}
+% {Explicitly set \cs{@currentcounter} (gh/687)}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease>\IncludeInRelease{2021/11/15}%
%<latexrelease> {\@mpfootnotetext}{footnotetext tagging}%
\long\def\@mpfootnotetext#1{%
\global\setbox\@mpfootins\vbox{%
@@ -1148,6 +1150,7 @@
\reset@font\footnotesize
\hsize\columnwidth
\@parboxrestore
+ \def\@currentcounter{mpfootnote}%
\protected@edef\@currentlabel
{\csname p@mpfootnote\endcsname\@thefnmark}%
\color@begingroup
@@ -1158,6 +1161,24 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@mpfootnotetext}{footnotetext tagging}%
+%<latexrelease>\long\def\@mpfootnotetext#1{%
+%<latexrelease> \global\setbox\@mpfootins\vbox{%
+%<latexrelease> \unvbox\@mpfootins
+%<latexrelease> \reset@font\footnotesize
+%<latexrelease> \hsize\columnwidth
+%<latexrelease> \@parboxrestore
+%<latexrelease> \protected@edef\@currentlabel
+%<latexrelease> {\csname p@mpfootnote\endcsname\@thefnmark}%
+%<latexrelease> \color@begingroup
+%<latexrelease> \@makefntext{%
+%<latexrelease> \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+%<latexrelease> \par
+%<latexrelease> \color@endgroup}}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
diff --git a/Master/texmf-dist/source/latex/base/ltclass.dtx b/Master/texmf-dist/source/latex/base/ltclass.dtx
index 2ab3081bf74..06e0f437af1 100644
--- a/Master/texmf-dist/source/latex/base/ltclass.dtx
+++ b/Master/texmf-dist/source/latex/base/ltclass.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltclass.dtx}
- [2021/06/06 v1.4c LaTeX Kernel (Class & Package Interface)]
+ [2021/08/25 v1.4f LaTeX Kernel (Class & Package Interface)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltclass.dtx}
@@ -68,6 +68,7 @@
% \changes{v1.0z}{1998/03/21}{Added to documentation of filecontents}
% \changes{v1.1c}{1998/08/17}{(RmS) Minor documentation fixes.}
% \changes{v1.3o}{2020/08/21}{Integration of new hook management interface}
+% \changes{v1.4f}{2021/08/25}{Standardise generic hook names (gh/648)}
%
%
% \section{Introduction}
@@ -311,27 +312,49 @@
% default option handler, which is not used for |landscape| as that
% option is explicitly declared.
%
+% \DescribeMacro\IfPackageLoadedTF
+% \DescribeMacro\IfClassLoadedTF
% \DescribeMacro\@ifpackageloaded
-% To find out if a package has already been loaded, use\\
% \DescribeMacro\@ifclassloaded
-% |\@ifpackageloaded{|\meta{package}|}{|\meta{true}|}{|\meta{false}|}|.
-%
+% To find out if a package has already been loaded, use
+% \begin{quote}
+% |\IfPackageLoadedTF{|\meta{package}|}{|\meta{true}|}{|\meta{false}|}|\\
+% \end{quote}
+% or the old name \cs{@ifpackageloaded}.
+%
+% \DescribeMacro\IfPackageAtLeastTF
+% \DescribeMacro\IfClassAtLeastTF
% \DescribeMacro\@ifpackagelater
+% \DescribeMacro\@ifclasslater
% \changes{v1.1i}{2013/07/07}{Correctly describe how the date in
% \cs{@ifpackagelater} is used}
% To find out if a package has already been loaded with a version
% equal to or more
-% recent than \meta{version}, use\\
-% \DescribeMacro\@ifclasslater
-% |\@ifpackagelater{|\meta{package}|}{|\meta{version}|}{|^^A
-% \meta{true}|}{|\meta{false}|}|.
-%
+% recent than \meta{date}, use
+% \begin{quote}
+% |\IfPackageAtLeastTF{|\meta{package}|}{|\meta{date}|}{|^^A
+% \meta{true}|}{|\meta{false}|}|
+% \end{quote}
+% or the old name \cs{@ifpackagelater}.
+
+% \DescribeMacro\IfFormatAtLeastTF
+% To test the format date use
+% \begin{quote}
+% |\IfFormatAtLeastTF{|\meta{date}|}{|^^A
+% \meta{true}|}{|\meta{false}|}|
+% \end{quote}
+%
+% \DescribeMacro\IfPackageLoadedWithOptionsTF
+% \DescribeMacro\IfClassLoadedWithOptionsTF
% \DescribeMacro\@ifpackagewith
+% \DescribeMacro\@ifclasswith
% To find out if a package has already been loaded with at least the
% options \meta{options}, use
-% \DescribeMacro\@ifclasswith
-% |\@ifpackagewith{|\meta{package}|}{|\meta{options}|}{|^^A
-% \meta{true}|}{|\meta{false}|}|.
+% \begin{quote}
+% |\IfPackageLoadedWithOptionsTF{|\meta{package}|}{|\meta{options}|}{|^^A
+% \meta{true}|}{|\meta{false}|}|
+% \end{quote}
+% or the old name \cs{@ifpackagewith}.
%
% There exists one package that can't be tested with the above
% commands: the \texttt{fontenc} package pretends that it was never
@@ -499,9 +522,10 @@
% \begin{macro}{\@classoptionslist}
% List of options of the main class.
% \changes{v1.0u}{1996/07/26}{made only preamble}
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\let\@classoptionslist\relax
-\@onlypreamble\@classoptionslist
+%\@onlypreamble\@classoptionslist
% \end{macrocode}
% \end{macro}
%
@@ -517,9 +541,10 @@
% \changes{v1.0u}{1996/07/26}{made only preamble}
% List of options of the main class that haven't been declared or
% loaded as class option files.
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\let\@unusedoptionlist\@empty
-\@onlypreamble\@unusedoptionlist
+%\@onlypreamble\@unusedoptionlist
% \end{macrocode}
% \end{macro}
%
@@ -571,11 +596,10 @@
% \begin{macro}{\@clsextension}
% \begin{macro}{\@pkgextension}
% The two possible values of |\@currext|.
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\def\@clsextension{cls}
\def\@pkgextension{sty}
-\@onlypreamble\@clsextension
-\@onlypreamble\@pkgextension
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -811,10 +835,11 @@
%
% \begin{macro}{\@ptionlist}
% Returns the option list of the file.
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\def\@ptionlist#1{%
\@ifundefined{opt@#1}\@empty{\csname opt@#1\endcsname}}
-\@onlypreamble\@ptionlist
+%\@onlypreamble\@ptionlist
% \end{macrocode}
% \end{macro}
%
@@ -824,11 +849,10 @@
% Checks to see whether a file has been loaded.
% \changes{v0.2t}{1994/01/18}
% {Fix typo \cs{@pkgetension}}
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\def\@ifpackageloaded{\@ifl@aded\@pkgextension}
\def\@ifclassloaded{\@ifl@aded\@clsextension}
-\@onlypreamble\@ifpackageloaded
-\@onlypreamble\@ifclassloaded
% \end{macrocode}
%
% \begin{macrocode}
@@ -838,11 +862,12 @@
\else
\expandafter\@firstoftwo
\fi}
-\@onlypreamble\@ifl@aded
% \end{macrocode}
% \end{macro}
% \end{macro}
%
+%
+%
% \begin{macro}{\@ifpackagelater}
% \begin{macro}{\@ifclasslater}
% |\@ifpackagelater{|\meta{name}|}{YYYY/MM/DD}{|\meta{true
@@ -852,17 +877,17 @@
% A better name for it would therefore been
% |\@ifpackagelaterorequal| but it is in use for more than 30
% years, so \ldots
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\def\@ifpackagelater{\@ifl@ter\@pkgextension}
\def\@ifclasslater{\@ifl@ter\@clsextension}
-\@onlypreamble\@ifpackagelater
-\@onlypreamble\@ifclasslater
% \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
+%
% \begin{macro}{\IfPackageAtLeastTF}
% \begin{macro}{\IfClassAtLeastTF}
% \begin{macro}{\IfFormatAtLeastTF}
@@ -870,6 +895,7 @@
% code}|}{|\meta{false code}|}|
% Test if the format is later or equal to the given date.
% \changes{v1.3k}{2020/04/07}{Macro added; also in rollback (gh/168)}
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
@@ -878,9 +904,6 @@
\def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
\let\IfPackageAtLeastTF\@ifpackagelater
\let\IfClassAtLeastTF\@ifclasslater
-\@onlypreamble\IfFormatAtLeastTF
-\@onlypreamble\IfPackageAtLeastTF
-\@onlypreamble\IfClassAtLeastTF
% \end{macrocode}
% For rollback pretend it was available since the beginning of dawn.
% \begin{macrocode}
@@ -899,11 +922,11 @@
% \end{macro}
%
% \begin{macro}{\@ifl@ter}
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\def\@ifl@ter#1#2{%
\expandafter\@ifl@t@r
\csname ver@#2.#1\endcsname}
-\@onlypreamble\@ifl@ter
%</2ekernel>
% \end{macrocode}
%
@@ -942,9 +965,6 @@
%<*2ekernel>
% \end{macrocode}
%
-% \begin{macrocode}
-\@onlypreamble\@ifl@t@r
-% \end{macrocode}
% \end{macro}
%
% \changes{v1.1j}{2016/06/20}
@@ -974,17 +994,15 @@
% |\@ifpackagewith{|\meta{name}|}{|\meta{option-list}|}|
% Checks that \meta{option-list} is a subset of the options
% \textbf{with} which \meta{name} was loaded.
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
\def\@ifpackagewith{\@if@ptions\@pkgextension}
\def\@ifclasswith{\@if@ptions\@clsextension}
-\@onlypreamble\@ifpackagewith
-\@onlypreamble\@ifclasswith
% \end{macrocode}
%
% \begin{macrocode}
\def\@if@ptions#1#2{%
\@expandtwoargs\@if@pti@ns{\@ptionlist{#2.#1}}}
-\@onlypreamble\@if@ptions
% \end{macrocode}
%
% Probably shouldn't use |\CurrentOption| here\ldots (changed to
@@ -993,6 +1011,7 @@
% {Add extra ,s so `two' is not matched with `twocolumn'}
% \changes{v1.1i}{2011/08/19}
% {Re-jig definition after more stringent \cs{in@} test.}
+% \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}}
% \begin{macrocode}
%</2ekernel>
%<latexrelease>\IncludeInRelease{2017/01/01}%
@@ -1038,12 +1057,45 @@
%<*2ekernel>
% \end{macrocode}
%
-% \begin{macrocode}
-\@onlypreamble\@if@pti@ns
-% \end{macrocode}
% \end{macro}
% \end{macro}
%
+%
+%
+%
+% \begin{macro}{\IfPackageLoadedTF,\IfPackageLoadedWithOptionsTF,
+% \IfClassLoadedTF,\IfClassLoadedWithOptionsTF}
+% More public names for the commands already available for a long time.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\IfPackageLoadedtTF}{Test package loading}%
+\let \IfPackageLoadedTF \@ifpackageloaded
+\let \IfClassLoadedTF \@ifclassloaded
+\let \IfPackageLoadedWithOptionsTF \@ifpackagewith
+\let \IfClassLoadedWithOptionsTF \@ifclasswith
+% \end{macrocode}
+% For rollback pretend it was available since the beginning of dawn.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\IfPackageLoadedtTF}{Test package loading}%
+%<latexrelease>
+%<latexrelease>\let \IfPackageLoadedTF \@ifpackageloaded
+%<latexrelease>\let \IfClassLoadedTF \@ifclassloaded
+%<latexrelease>\let \IfPackageLoadedWithOptionsTF \@ifpackagewith
+%<latexrelease>\let \IfClassLoadedWithOptionsTF \@ifclasswith
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
% \begin{macro}{\ProvidesPackage}
% Checks that the current filename is correct, and defines
% |\ver@filename|.
@@ -1979,8 +2031,9 @@
\ifx\@nnil##1\@nnil\else
% \end{macrocode}
%
+% \changes{v1.4d}{2021/07/12}{add \cs{unexpanded}}
% \begin{macrocode}
- \noexpand\@onefilewithoptions##1[{#2}][{#4}]%
+ \noexpand\@onefilewithoptions##1[{\unexpanded{#2}}][{#4}]%
\noexpand\@pkgextension
\fi
\expandafter\reserved@b
@@ -2289,7 +2342,7 @@
% \changes{v1.3u}{2020/11/20}
% {Copy option list to the requested package.}
% \changes{v1.4c}{2021/06/06}
-% {Copy raw raw options for gh/580}
+% {Copy raw options for gh/580}
% \begin{macrocode}
\expandafter\let
\csname opt@\@currpkg@reqd\expandafter\endcsname
@@ -2309,15 +2362,17 @@
% package otherwise, if it is \cs{@clsextension}, a class, so
% depending on that we execute different hooks. If the extension is
% neither, then it is another type of file without special hooks.
+% \changes{v1.4e}{2021/07/23}{Make class/name/before a one-time hook}
+% \changes{v1.4e}{2021/07/23}{Make package/name/before a one-time hook}
% \begin{macrocode}
%-----------------------------------------
\ifx\@currext\@pkgextension
\UseHook{package/before}%
- \UseHook{package/before/\@currname}%
+ \UseOneTimeHook{package/\@currname/before}%
\else
\ifx\@currext\@clsextension
\UseHook{class/before}%
- \UseHook{class/before/\@currname}%
+ \UseOneTimeHook{class/\@currname/before}%
\fi
\fi
% \end{macrocode}
@@ -2376,27 +2431,35 @@
% \end{macrocode}
% And same procedure, James, when we are finished loading, except
% that the hook order is now reversed.
+% \changes{v1.4e}{2021/07/23}{Make class/name/after a one-time hook}
+% \changes{v1.4e}{2021/07/23}{Make package/name/after a one-time hook}
% \begin{macrocode}
%-----------------------------------------
\ifx\@currext\@pkgextension
- \UseHook{package/after/\@currname}%
+ \UseOneTimeHook{package/\@currname/after}%
\UseHook{package/after}%
\else
\ifx\@currext\@clsextension
- \UseHook{class/after/\@currname}%
+ \UseOneTimeHook{class/\@currname/after}%
\UseHook{class/after}%
\fi
\fi}%
%-----------------------------------------
\@ifl@aded\@currext\@currname{}{\reserved@a}}
% \end{macrocode}
-% \end{macro}
-%
+%
+% \changes{v1.4f}{2021/08/25}{Declare non-generic package and class hooks}
+% Now declare the non-generic package and class hooks used above:
% \begin{macrocode}
-%</2ekernel|latexrelease>
+\NewHook{package/before}
+\NewHook{class/before}
+\NewReversedHook{package/after}
+\NewReversedHook{class/after}
% \end{macrocode}
-%
+% \end{macro}
+%
% \begin{macrocode}
+%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\@onefilewithoptions}{Hooks and unused options issue}%
@@ -2771,11 +2834,12 @@
% \end{macrocode}
%
% Lua\TeX\ has more writes (and 18 is safe here).
+% \changes{v1.4b}{2021/06/09}{Use \cs{@latex@note@no@line} to display the information}
% \begin{macrocode}
\chardef\reserved@c\ifx\directlua\@undefined 15 \else 127 \fi%
\openin\@inputcheck\q@curr@file \space %
\ifeof\@inputcheck%
- \@latex@warning@no@line%
+ \@latex@note@no@line%
{Writing file `\@currdir\@curr@file'}%
% \end{macrocode}
%
@@ -2789,9 +2853,10 @@
%
% \changes{v1.0y}{1997/10/10}
% {Use \cs{@gobbletwo}}
+% \changes{v1.4b}{2021/06/09}{Use \cs{@latex@note@no@line} to display the information}
% \begin{macrocode}
\if@filesw%
- \@latex@warning@no@line%
+ \@latex@note@no@line%
{File `\@curr@file' already \filec@ntents@where.\MessageBreak%
Not generating it from this source}%
\let\write\@gobbletwo%
diff --git a/Master/texmf-dist/source/latex/base/ltcmd.dtx b/Master/texmf-dist/source/latex/base/ltcmd.dtx
index 806161d5386..04be2abfbfd 100644
--- a/Master/texmf-dist/source/latex/base/ltcmd.dtx
+++ b/Master/texmf-dist/source/latex/base/ltcmd.dtx
@@ -34,8 +34,8 @@
%%% From File: ltcmd.dtx
%
% \begin{macrocode}
-\def\ltcmdversion{v1.0e}
-\def\ltcmddate{2021-05-24}
+\def\ltcmdversion{v1.0h}
+\def\ltcmddate{2021-08-30}
% \end{macrocode}
%
%<*driver>
@@ -343,8 +343,7 @@
%
% \begin{macro}{\@@_declare_cmd:Nnn, \@@_declare_expandable_cmd:Nnn}
% \begin{macro}{\@@_declare_cmd_aux:Nnn}
-% \begin{macro}
-% {\@@_declare_cmd_internal:Nnnn, \@@_declare_cmd_internal:cnxn}
+% \begin{macro}{\@@_declare_cmd_internal:Nnnn}
% The main functions for creating commands set the appropriate flag then
% use the same internal code to do the definition.
% \begin{macrocode}
@@ -366,7 +365,7 @@
{
\cs_if_exist:NTF #1
{
- \msg_info:nnxx { cmd } { redefine-command }
+ \msg_info:nnxx { cmd } { redefine }
{ \token_to_str:N #1 } { \tl_to_str:n {#2} }
}
{
@@ -400,7 +399,6 @@
#4
\@@_break_point:n {#2}
}
-\cs_generate_variant:Nn \@@_declare_cmd_internal:Nnnn { cnx }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -536,11 +534,11 @@
{ \tl_trim_spaces:o { \l_@@_environment_str } }
\cs_if_exist:cTF { \l_@@_environment_str }
{
- \msg_info:nnxx { cmd } { redefine-environment }
+ \msg_info:nnxx { cmd } { redefine-env }
{ \l_@@_environment_str } { \tl_to_str:n {#2} }
}
{
- \msg_info:nnxx { cmd } { define-environment }
+ \msg_info:nnxx { cmd } { define-env }
{ \l_@@_environment_str } { \tl_to_str:n {#2} }
}
\bool_set_false:N \l_@@_expandable_bool
@@ -565,15 +563,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_declare_env_internal:nnnn #1#2#3#4
{
- \@@_declare_cmd_internal:cnxn { environment~ #1 } {#2}
- {
- \cs_set_nopar:Npx \exp_not:c { environment~ #1 ~end~aux }
- {
- \exp_not:N \exp_not:N \exp_not:c { environment~ #1~end~aux~ }
- \exp_not:n { \exp_not:o \l_@@_args_tl }
- }
- \exp_not:n {#3}
- }
+ \exp_args:Nc \@@_declare_cmd_internal:Nnnn { environment~ #1 } {#2}
+ {#3}
{
\cs_set_nopar:cpx { environment~ #1 ~end }
{ \exp_not:c { environment~ #1 ~end~aux } }
@@ -584,6 +575,14 @@
\cs_set_eq:cc { end #1 } { environment~ #1 ~end }
}
}
+\cs_new_protected:Npn \@@_set_environment_end:n #1
+ {
+ \cs_set_nopar:cpx { environment~ #1 ~end~aux }
+ {
+ \exp_not:c { environment~ #1 ~end~aux~ }
+ \exp_not:o \l_@@_args_tl
+ }
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -639,7 +638,10 @@
\tl_set:Nn \l_@@_fn_code_tl {#2}
\tl_set:Nn \l_@@_defaults_tl {#5}
\tl_set:Nn \l_@@_process_all_tl {#6}
- #4 \@@_run_code:
+ #4
+ \bool_if:NT \l_@@_environment_bool
+ { \exp_args:No \@@_set_environment_end:n \l_@@_environment_str }
+ \@@_run_code:
}
\cs_generate_variant:Nn \@@_start_aux:NNnnnn { cc }
% \end{macrocode}
@@ -693,7 +695,7 @@
}
\cs_new_protected:Npn \@@_defaults_error:w \q_recursion_stop
{
- \msg_error:nnx { cmd } { loop-in-defaults }
+ \msg_error:nnx { cmd } { default-loop }
{ \@@_environment_or_command: }
}
% \end{macrocode}
@@ -821,7 +823,7 @@
\@@_end_expandable_defaults:nnnNNn {#1} { } {#1} #2#3
{ } { } { } { } { } { } { } { } { } { }
{
- \msg_expandable_error:nnf { cmd } { loop-in-defaults }
+ \msg_expandable_error:nnf { cmd } { default-loop }
{ \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N #4 } }
\use_iv:nnnn
}
@@ -919,7 +921,7 @@
\q_recursion_tail \q_recursion_tail \q_recursion_tail \q_recursion_stop
\int_compare:nNnT \l_@@_current_arg_int > 9
{
- \msg_error:nnxx { cmd } { too-many-arguments }
+ \msg_error:nnxx { cmd } { too-many-args }
{ \@@_environment_or_command: } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
@@ -951,7 +953,7 @@
{ \str_if_eq_p:nn {#1} { u } }
}
{
- \msg_error:nnxx { cmd } { xparse-argument-type }
+ \msg_error:nnxx { cmd } { xparse-arg-type }
{ \@@_environment_or_command: } { \tl_to_str:n {#1} }
}
{
@@ -1241,7 +1243,7 @@
{ \use_none:n }
}
{
- \msg_error:nnxxx { cmd } { forbidden-implicit-group-token }
+ \msg_error:nnxxx { cmd } { forbidden-group-token }
{ \@@_environment_or_command: } { \tl_to_str:n {#1} }
{
\token_if_eq_meaning:NNTF #1 \c_group_begin_token
@@ -1261,7 +1263,7 @@
{
\bool_if:NT \l_@@_expandable_bool
{
- \msg_error:nnxx { cmd } { invalid-expandable-argument-type }
+ \msg_error:nnxx { cmd } { invalid-expandable-arg }
{ \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
@@ -1334,7 +1336,7 @@
{
\bool_if:NT \l_@@_expandable_bool
{
- \msg_error:nnx { cmd } { inconsistent-long }
+ \msg_error:nnx { cmd } { long-short-mix }
{ \iow_char:N \\ \l_@@_function_tl }
\@@_bad_def:wn
}
@@ -1356,7 +1358,7 @@
{
\bool_if:NT \l_@@_some_obey_spaces_bool
{
- \msg_error:nnxx { cmd } { non-trailing-obey-spaces }
+ \msg_error:nnxx { cmd } { invalid-bang }
{ \@@_environment_or_command: } { \tl_to_str:n {#1} }
\@@_bad_def:wn
}
@@ -1505,12 +1507,21 @@
%
% \begin{macro}{\@@_add_type_E:w}
% The \texttt{E}-type argument needs a special handling of default
-% values.
+% values. Since each embellishment is a separate argument, it
+% also needs to replicate the argument processors for each embellishment
+% argument so that the numbers of arguments and processors remain in sync.
+% \changes{v1.0g}{2021/08/07}
+% {Replicate argument processors for all embellishments (gh/639)}
% \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_E:w #1#2
{
\@@_flush_m_args:
\@@_add_default_E:nn {#1} {#2}
+ \use:x
+ {
+ \@@_replicate_processor:nn { \tl_count:n {#1} }
+ { \exp_not:o \l_@@_process_one_tl }
+ }
\@@_add_grabber:N E
\tl_put_right:Nn \l_@@_signature_tl { {#1} }
\@@_prepare_signature:N
@@ -1518,6 +1529,48 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_replicate_processor:nn}
+% In the command's argument processor signature (the final argument of
+% \cs{@@_start:nNNnnn}) there is one braced item for each formal
+% argument (up to nine), and in each of these items there is one
+% braced item for each processor (as many as there were processors
+% declared for a given argument). Something like this:
+% \begin{quote}
+% \ttfamily \obeylines
+% \{ \% argument processors
+% \ \ \{ \% argument 1
+% \ \ \ \ \{ processor 1 \} \{ processor 2 \} \ldots\ \{ processor n \}
+% \ \ \} \% end argument 1
+% \ \ \{ \ldots\ \} \% argument 2
+% \ \ \ \ \ \vdots
+% \ \ \{ \ldots\ \} \% argument n
+% \} \% end argument processors
+% \end{quote}
+%
+% The function \cs{@@_add_grabber:N} adds one single grabber for an
+% argument, and adds the braced item for that one argument. However,
+% in an |E|-type argument each embellishment requires its own formal
+% argument, so we need to break out of one layer of braces in
+% \cs{l_@@_process_one_tl}, add copies of the processor as necessary,
+% and then return the removed brace. The function below does just
+% that: it defines \cs{l_@@_process_one_tl} starting with a |}|$_2$
+% and ending with a |{|$_1$, so that it adds as many processors as
+% needed when |x|-expanded.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_replicate_processor:nn #1 #2
+ {
+ \int_compare:nNnF {#1} > { 1 } { \use_none:nnn }
+ \tl_set:Nx \l_@@_process_one_tl
+ {
+ \exp_not:n { \exp_not:n {#2} \if_false: { \fi: } }
+ \prg_replicate:nn { #1 - 2 }
+ { \exp_not:n { \exp_not:n { {#2} } } }
+ \exp_not:n { { \if_false: } \fi: \exp_not:n {#2} }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_add_type_m:w}
% The \texttt{m} type is special as short arguments which are not
% post-processed are simply counted at this stage. Thus there is a check
@@ -1608,6 +1661,8 @@
% \cs{l_@@_obey_spaces_bool} boolean can only be \texttt{true} for
% trailing optional arguments. In that case spaces will not be
% ignored when looking for that optional argument.
+% \changes{v1.0g}{2021/08/07}
+% {Replicate argument processors for all embellishments (gh/639)}
% \begin{macrocode}
\cs_new_protected:Npn \@@_add_grabber:N #1
{
@@ -1624,7 +1679,12 @@
\bool_set_false:N \l_@@_long_bool
\bool_set_false:N \l_@@_obey_spaces_bool
\tl_put_right:Nx \l_@@_process_all_tl
- { { \exp_not:o \l_@@_process_one_tl } }
+ {
+ {
+ \if_charcode:w E #1 \use_i:nn \fi:
+ \exp_not:o \l_@@_process_one_tl
+ }
+ }
\tl_clear:N \l_@@_process_one_tl
}
% \end{macrocode}
@@ -1676,8 +1736,7 @@
% We have already checked that short arguments are before long
% arguments, so \cs{l_@@_long_bool} only changes from \texttt{false}
% to \texttt{true} once (and there is no need to reset it after each
-% argument). Also knock back the argument count because |+| is not an
-% argument. Continue the loop.
+% argument). Continue the loop.
% \begin{macrocode}
\cs_new_protected:cpn { @@_add_expandable_type_+:w }
{
@@ -1875,6 +1934,657 @@
% \end{macro}
% \end{macro}
%
+% \subsubsection{Copying a command and its internal structure}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_copy:NN}%
+%<latexrelease> {Support~\NewCommandCopy~in~ltcmd}
+% \end{macrocode}
+%
+% \changes{v1.0h}{2021/08/30}{Added support for \cs{NewCommandCopy}}
+% Since the 2020-10-01 \LaTeXe{} release, support for copying, and
+% showing the definition of, robust commands has been available, but the
+% specifics of each command are implemented separately. Here we'll add
+% support for copying and showing \pkg{ltcmd} definitions.
+%
+% To fully support copying, we need two commands: a conditional to test
+% if a command is in fact a \pkg{ltcmd} command, and another command to
+% actually copy the command. The conditional is defined later as
+% \cs{__kernel_cmd_if_xparse:NTF}, so now to the copying:
+%
+% \begin{macro}{\@@_copy:NN}
+% \begin{macro}{\@@_set_eq_if_exist:NN,\@@_set_eq_if_exist:cc}
+% This macro just branches to the proper copying command by using
+% \cs{@@_cmd_type_cases:NnnnnF}. The copying command takes the names
+% of the commands to be copied to and from, and the actual commands
+% as its four arguments.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy:NN #1 #2
+ {
+ \use:x
+ {
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \exp_not:N \@@_cmd_type_cases:NnnnnF \exp_not:N #2
+ { \@@_copy_command:nnNN }
+ { \@@_copy_expandable:nnNN }
+ { \@@_copy_environment:nnNN }
+ { \@@_copy_environment_end:nnNN }
+ { \@@_cant_copy:nwn { non-ltcmd } }
+ { \cs_to_str:N #1 } { \cs_to_str:N #2 }
+ \exp_not:N #1 \exp_not:N #2
+ \exp_not:N \@@_break_point:n { \cs_to_str:N #2 }
+ \int_set:Nn \tex_escapechar:D { \int_use:N \tex_escapechar:D }
+ }
+ }
+\cs_new_protected:Npn \@@_set_eq_if_exist:NN #1 #2
+ { \cs_if_exist:NTF #2 { \cs_set_eq:NN } { \use_none:nn } #1 #2 }
+\cs_generate_variant:Nn \@@_set_eq_if_exist:NN { cc }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_cant_copy:nwn}
+% An utility macro similar to \cs{@@_bad_def:wn} to abort a command
+% copy. Contrary to \cs{@@_bad_def:wn} though, when this happens the
+% issue is most likely internal, because the command was already
+% (supposedly) correcly defined so it should be copyable. Hopefully
+% this macro will never be used ever, but if it does, apologise and
+% give the reason for the failure so the user can report.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cant_copy:nwn #1 #2 \@@_break_point:n #3
+ { \msg_error:nnnn { cmd } { copy-bug } {#1} {#3} }
+\msg_new:nnn { cmd } { copy-bug }
+ {
+ Error~while~copying~command~\iow_char:N\\#2:\\
+ \str_case:nn {#1}
+ {
+ { non-ltcmd } { Command~is~not~a~valid~ltcmd~command. }
+ { unknown-type } { Found~an~unknown~argument~type. }
+ { invalid-end }
+ { Target~command~is~not~named~\iow_char:N \\end<name>. }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% And, of course, add \cs{__kernel_cmd_if_xparse:NTF} and
+% \cs{@@_copy:NN} to \cs{@declarecommandcopylisthook}:
+% \begin{macrocode}
+\tl_gput_right:Nn \@declarecommandcopylisthook
+ { { \__kernel_cmd_if_xparse:NTF \@@_copy:NN } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_copy_command:nnNN,\@@_copy_command:NnNNnnnn}
+% A normal (non-expandable) command has a pretty straightforward
+% structure. Its definition is stored in
+% \cs{\meta{cmd}\textvisiblespace code}, its defaults (if any) are
+% stored in \cs{\meta{cmd}\textvisiblespace defaults}, and its
+% top-level definition contains its signature, which can just be
+% copied over. \cs{@@_copy_command:nnNN} copies the command code and
+% defaults, and then defines the top-level command using the auxiliary
+% \cs{@@_copy_command:NnNNnnnn}. This macro takes the signature of
+% the command being copied from its top-level definition, and replaces
+% the named bits with the new name.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_command:nnNN #1 #2 #3 #4
+ {
+ \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
+ \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults }
+ \cs_set_protected_nopar:Npx #3
+ { \exp_after:wN \@@_copy_command:NnNNnnnn #4 {#1} }
+ }
+\cs_new:Npn \@@_copy_command:NnNNnnnn #1 #2 #3 #4 #5 #6 #7 #8
+ {
+ #1 \exp_not:n { {#2} }
+ \exp_not:c { #8 ~ } \exp_not:c { #8 ~ code }
+ \exp_not:n { {#5} {#6} {#7} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_copy_expandable:nnNN,\@@_copy_expandable:NnNNNNnnn}
+% An expandable command is slightly more complicated. Besides the
+% \cs{\meta{cmd}\textvisiblespace code}, and
+% \cs{\meta{cmd}\textvisiblespace defaults}, it also has an auxiliary
+% \cs{\meta{cmd}\textvisiblespace} for grabbing delimited arguments,
+% and possibly another auxiliary
+% \cs{\meta{cmd}\textvisiblespace\textvisiblespace}, if the command
+% has both long and short arguments. Then, its signature also has
+% several specific bits that are unique to that command; this is in contrast to
+% non-expandable commands, which use a common set of parsing functions.
+%
+% We start by copying the basics, then call
+% \cs{@@_copy_expandable_signature:NnNNNNnnn} to parse the signature
+% of the command and build up the modified copy in a temporary token list,
+% then we call \cs{@@_copy_expandable:NnNNNNnnn} that will copy the
+% top-level definition of the command, with the proper internal
+% renames.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_expandable:nnNN #1 #2 #3 #4
+ {
+ \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
+ \@@_set_eq_if_exist:cc { #1 ~ } { #2 ~ }
+ \@@_set_eq_if_exist:cc { #1 ~ \c_space_tl } { #2 ~ \c_space_tl }
+ \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults }
+ \exp_after:wN \@@_copy_expandable_signature:NnNNNNnnn #4 {#1} {#2}
+ \cs_set_nopar:Npx #3
+ { \exp_after:wN \@@_copy_expandable:NnNNNNnnn #4 {#1} {#2} }
+ }
+\cs_new:Npn \@@_copy_expandable:NnNNNNnnn #1 #2 #3 #4 #5 #6 #7 #8 #9
+ {
+ \exp_not:N #1 \exp_not:n { {#2} }
+ \exp_not:c { #8 ~ }
+ \exp_not:c
+ {
+ #8 ~
+ \str_if_eq:eeT
+ { \exp_not:c { #9 ~ \c_space_tl } } { \exp_not:N #4 }
+ { \c_space_tl }
+ }
+ \exp_not:c { #8 ~ code }
+ \str_if_eq:eeTF { \exp_not:N #6 } { ? }
+ { ? }
+ { \exp_not:c { #8 ~ defaults } }
+ { \exp_not:V \l_@@_tmpa_tl }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_copy_expandable_signature:NnNNNNnnn,
+% \@@_copy_expandable:nnN,
+% \@@_copy_parse_grabber:w,
+% }
+% A signature for an expandable command contains as many
+% \cs{expandable_grab_\meta{type}:w} as there are arguments, and what
+% follows this macro depends on the \meta{type}. We'll start a loop
+% through the signature, and at each argument grabber, we'll step the
+% argument count, and look for the \meta{type} with
+% \cs{@@_copy_parse_grabber:w} so that we know which
+% \cs{@@_copy_grabber_\meta{type}:w} to call next.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_expandable_signature:NnNNNNnnn
+ #1 #2 #3 #4 #5 #6 #7 #8 #9
+ {
+ \int_zero:N \l_@@_current_arg_int
+ \tl_clear:N \l_@@_tmpa_tl
+ \@@_copy_expandable:nnN {#8} {#9} #7
+ \q_recursion_tail \q_recursion_stop
+ }
+\cs_new_protected:Npn \@@_copy_expandable:nnN #1 #2 #3
+ {
+ \quark_if_recursion_tail_stop:n {#3}
+ \int_incr:N \l_@@_current_arg_int
+ \exp_after:wN \@@_copy_parse_grabber:w \token_to_str:N #3 {#1} {#2}
+ }
+\use:x
+ {
+ \cs_new_protected:Npn \exp_not:N \@@_copy_parse_grabber:w ##1
+ \tl_to_str:n { expandable_grab_ } ##2 \tl_to_str:n { :w }
+ {
+ \tl_put_right:Nx \exp_not:N \l_@@_tmpa_tl
+ { \exp_not:N \exp_not:c { @@_expandable_grab_##2:w } }
+ \exp_not:N \cs_if_exist_use:cF { @@_copy_grabber_##2:w }
+ { \@@_cant_copy:nwn { unknown-type } }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_copy_grabber_D:w,\@@_copy_grabber_D_alt:w,
+% \@@_copy_grabber_R:w,\@@_copy_grabber_R_alt:w,
+% \@@_copy_grabber_E:w,\@@_copy_grabber_E_long:w,
+% \@@_copy_grabber_t:w,
+% \@@_copy_grabber_m:w,\@@_copy_grabber_m_long:w,
+% }
+% The most complicated is the |D|elimited argument: each argument has
+% a dedicated grabbing function named after the command that has to be
+% copied over (of the form
+% \cs{\meta{cmd}\textvisiblespace(arg\textvisiblespace\meta{num})}).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_grabber_D:w #1 #2 #3 #4 #5
+ {
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ \exp_not:c { #1 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
+ \exp_not:n { #4 #5 }
+ }
+ \cs_set_eq:cc
+ { #1 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
+ { #2 ~ (arg ~ \int_use:N \l_@@_current_arg_int ) }
+ \@@_copy_expandable:nnN {#1} {#2}
+ }
+% \end{macrocode}
+%
+% |D_alt| is just a special case of |D| that uses a single delimiter
+% (used when both delimiters of the argument are identical):
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_grabber_D_alt:w #1 #2 #3 #4
+ { \@@_copy_grabber_D:w {#1} {#2} {#3} {#4} { } }
+% \end{macrocode}
+%
+% As far as copying is concerned, |R| is identical to |D|:
+% \begin{macrocode}
+\cs_new_eq:NN \@@_copy_grabber_R:w \@@_copy_grabber_D:w
+\cs_new_eq:NN \@@_copy_grabber_R_alt:w \@@_copy_grabber_D_alt:w
+% \end{macrocode}
+%
+% |E| is straightforward: we just copy the embellishments over, and
+% increase the current argument number \cs{l_@@_current_arg_int} by
+% the number of embellishments (minus one because there is a
+% \cs{int_incr:N} down the line).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_grabber_E:w #1 #2 #3 #4
+ {
+ \tl_put_right:Nn \l_@@_tmpa_tl { {#3} {#4} }
+ \int_add:Nn \l_@@_current_arg_int { \tl_count:n {#4} - 1 }
+ \@@_copy_expandable:nnN {#1} {#2}
+ }
+\cs_new_eq:NN \@@_copy_grabber_E_long:w \@@_copy_grabber_E:w
+% \end{macrocode}
+%
+% |t| just needs copying the token to be tested for:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_grabber_t:w #1 #2 #3 #4
+ {
+ \tl_put_right:Nn \l_@@_tmpa_tl { #3 #4 }
+ \@@_copy_expandable:nnN {#1} {#2}
+ }
+% \end{macrocode}
+%
+% And last but not least, |m| is the simplest; the grabber is just
+% \cs{@@_expandable_grab_m:w}, which is already added to the new
+% command so here we just resume the loop:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_grabber_m:w { \@@_copy_expandable:nnN }
+\cs_new_eq:NN \@@_copy_grabber_m_long:w \@@_copy_grabber_m:w
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_copy_environment:nnNN}
+% \begin{macro}{\@@_copy_environment:Nnnnnnn}
+% Copying an environment's \cs{begin} part is pretty much like copying
+% a command, except it has a longer name, and at the end we have to
+% copy \cs[no-index]{environment~\meta{name}} into
+% \cs[no-index]{\meta{name}}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_environment:nnNN #1 #2 #3 #4
+ {
+ \cs_set_eq:cc { environment~ #1 ~ code } { environment~ #2 ~ code }
+ \@@_set_eq_if_exist:cc
+ { environment~ #1 ~ defaults } { environment~ #2 ~ defaults }
+ \cs_set_protected_nopar:cpx { environment~ #1 }
+ { \exp_after:wN \@@_copy_environment:Nnnnnnn #4 {#1} }
+ \cs_set_eq:cc {#1} { environment~ #1 }
+ }
+\cs_new:Npn \@@_copy_environment:Nnnnnnn #1 #2 #3 #4 #5 #6 #7
+ { #1 \exp_not:n { {#2} } {#7} \exp_not:n { {#4} {#5} {#6} } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_copy_environment_end:nnNN}
+% \begin{macro}{\@@_copy_environment_end_aux:nnNN}
+% Copying an environment's \cs{end} part is a bit trickier. We first
+% have to make sure that both parts are named
+% \cs[no-index]{end\meta{name}} (that's actually not a hard
+% requirement, but an environment \cs{end} command makes no sense
+% without the |end| in its name), and strip the leading |end| from the
+% strings. After that, copying is straightforward.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_environment_end:nnNN #1 #2
+ {
+ \@@_check_end:Nn \l_@@_tmpa_tl {#1}
+ \@@_check_end:Nn \l_@@_tmpb_tl {#2}
+ \exp_args:Noo \@@_copy_environment_end_aux:nnNN
+ { \l_@@_tmpa_tl } { \l_@@_tmpb_tl }
+ }
+\cs_new_protected:Npn \@@_copy_environment_end_aux:nnNN #1 #2 #3 #4
+ {
+ \cs_set_nopar:cpx { environment~ #1 ~end }
+ { \exp_not:c { environment~ #1 ~end~aux } }
+ \cs_set_eq:cc
+ { environment~ #1 ~end~aux~ } { environment~ #2 ~end~aux~ }
+ \cs_set_eq:cc { end #1 } { environment~ #1 ~end }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_check_end:Nn,\@@_check_end:n,\@@_check_end:w}
+% To check whether an \cs{end} command is valid, we look for the
+% string |end| at the beginning of the command name, and if not found,
+% raise an error:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_check_end:Nn #1 #2
+ {
+ \tl_set:Nx #1 { \@@_check_end:n {#2} }
+ \token_if_eq_meaning:NNT #1 \q_nil
+ { \@@_cant_copy:nwn { invalid-end } }
+ }
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new:Npn \@@_check_end:n ##1
+ {
+ \exp_after:wN \@@_check_end:w \tl_to_str:n {##1}
+ #1 \q_mark #1 \q_stop
+ }
+ \cs_new:Npn \@@_check_end:w ##1 #1 ##2 #1 ##3 \q_stop
+ { \if_meaning:w ##2 \q_mark \exp_not:N \q_nil \else: ##2 \fi: }
+ }
+\exp_args:No \@@_tmp:w { \tl_to_str:n { end } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% Not much to do regarding \pkg{latexrelease}: we could remove the
+% entries from \cs{@declarecommandcopylisthook}, but it doesn't seem
+% worth it.
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_copy:NN}%
+%<latexrelease> {Support~\NewCommandCopy~in~ltcmd}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \subsubsection{Showing the definition of a command}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_show:N}%
+%<latexrelease> {Support~\ShowCommand~in~ltcmd}
+% \end{macrocode}
+%
+% \changes{v1.0h}{2021/08/30}{Added support for \cs{ShowCommand}}
+% To show the definition of a command we need more or less the same
+% building blocks as for copying, except that instead of making a copy,
+% we'll just print stuff to the terminal.
+%
+% \begin{macro}{\@@_show:N}
+% This macro just branches to the proper showing command by using
+% \cs{@@_cmd_type_cases:NnnnnF}. The showing command takes the command
+% to be shown as argument.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show:N #1
+ {
+ \use:x
+ {
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \exp_not:N \@@_cmd_type_cases:NnnnnF \exp_not:N #1
+ { \@@_show_command:N }
+ { \@@_show_expandable:N }
+ { \@@_show_environment:N }
+ { \@@_show_environment_end:N }
+ { \@@_cant_copy:nwn { non-ltcmd } }
+ \exp_not:N #1
+ \exp_not:N \@@_break_point:n { \cs_to_str:N #1 }
+ \int_set:Nn \tex_escapechar:D { \int_use:N \tex_escapechar:D }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_show_command:N,
+% \@@_show_command:NnNNwN,
+% \@@_show_expandable:N,
+% \@@_show_expandable:NnNNNNnN,
+% \@@_show_command_aux:nNNn,
+% \@@_show_environment:N,
+% }
+% These commands just expand the command once to reveal its innards,
+% then pass the type of command, the control sequence, the signature,
+% and the code macro to \cs{@@_show_command_aux:nNNn}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_command:N #1
+ { \exp_after:wN \@@_show_command:NnNNwN #1 \q_@@ #1 }
+\cs_new_protected:Npn \@@_show_command:NnNNwN #1 #2 #3 #4 #5 \q_@@ #6
+ { \@@_show_command_aux:nNNn { document~command } #6 #4 {#2} }
+\cs_new_protected:Npn \@@_show_expandable:N #1
+ { \exp_after:wN \@@_show_expandable:NnNNNNnN #1 #1 }
+\cs_new_protected:Npn \@@_show_expandable:NnNNNNnN #1 #2 #3 #4 #5 #6 #7 #8
+ { \@@_show_command_aux:nNNn { expandable~document~command } #8 #5 {#2} }
+% \end{macrocode}
+%
+% Now just print everything in the required format. The auxiliary
+% \cs{@@_split_signature:n} stores a ready-to-print token list in
+% \cs{l_@@_tmpa_tl}, so we ust use that here:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_command_aux:nNNn #1 #2 #3 #4
+ {
+ \@@_split_signature:n {#4}
+ \iow_term:x
+ {
+ > ~ \token_to_str:N #2 = #1: \iow_newline:
+ \tl_use:N \l_@@_tmpa_tl
+ -> \cs_replacement_spec:N #3 .
+ }
+ }
+% \end{macrocode}
+%
+% We can reuse most of the above to show an environment, except that
+% we need to ensure that the proper \cs[no-index]{environment~\ldots}
+% are passed to \cs{@@_show_command_aux:nNNn}. Additionally, when
+% |\ShowCommand\foo| is used (if |foo| is an environment), we show
+% |\endfoo| as well, and when |\ShowCommand\endfoo| is used, change
+% that to |\ShowCommand\foo| and do the same.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_environment:N #1
+ {
+ \exp_after:wN \@@_show_environment:Nnnw #1 \q_@@
+ \iow_term:x
+ {
+ > ~ \token_to_str:N \end { \cs_to_str:N #1 } : \iow_newline:
+ -> \exp_args:Nc \cs_replacement_spec:N
+ { environment~ \cs_to_str:N #1 ~end~aux~ } .
+ }
+ }
+\cs_new_protected:Npn \@@_show_environment:Nnnw #1 #2 #3 #4 \q_@@
+ {
+ \use:x
+ {
+ \@@_show_command_aux:nNNn { document~environment }
+ { \exp_not:N \begin {#3} }
+ \exp_not:c { environment~ #3 ~ code }
+ {#2}
+ }
+ }
+\cs_new_protected:Npn \@@_show_environment_end:N #1
+ {
+ \exp_args:NNx \@@_check_end:Nn \l_@@_tmpa_tl { \cs_to_str:N #1 }
+ \exp_args:Nc \@@_show_environment:N { \l_@@_tmpa_tl }
+ }
+% \end{macrocode}
+%
+% And, of course, add \cs{__kernel_cmd_if_xparse:NTF} and
+% \cs{@@_show:N} to \cs{@showcommandlisthook}:
+% \begin{macrocode}
+\tl_gput_right:Nn \@showcommandlisthook
+ { { \__kernel_cmd_if_xparse:NTF \@@_show:N } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_split_signature:n}
+% Now we'll try a least-effort adventure into splitting the symbolic
+% user-provided signature for a command into individual parameters for
+% pretty-printing. A counter is used to keep track of the current
+% argument number, and two token lists are used: \cs{l_@@_tmpa_tl}
+% holds the final token list to be printed, and \cs{l_@@_tmpb_tl}
+% holds just the current item, so that we can make changes to an
+% individual item without having to dissect the whole thing (this is
+% used for |e|- and |E|-types).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_split_signature:n #1
+ {
+ \int_set:Nn \l_@@_current_arg_int { 1 }
+ \tl_clear:N \l_@@_tmpa_tl
+ \tl_clear:N \l_@@_tmpb_tl
+ \@@_split_signature_loop:Nw #1 \q_recursion_tail \q_recursion_stop
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_split_signature_loop:Nw}
+% This is the main chunk of the loop: it starts an item with
+% \cs{@@_split_start_item:}
+% (this adds indentation and the argument number to
+% \cs{l_@@_tmpb_tl}), then checks if a special token list
+% \cs[no-index]{c_@@_show_type_\meta{type}_tl} exists. If it doesn't,
+% the current argument is a ``simple'' type which needs no extra
+% processing. Otherwise, call a specific function depending on the
+% value of said token list.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_split_signature_loop:Nw #1
+ {
+ \quark_if_recursion_tail_stop:N #1
+ \tl_if_empty:NT \l_@@_tmpb_tl { \@@_split_start_item: }
+ \tl_if_exist:cTF { c_@@_show_type_#1_tl }
+ {
+ \use:c
+ {
+ @@_show_
+ \if_case:w \tl_use:c { c_@@_show_type_#1_tl } \exp_stop_f:
+ delim \or: delims \or: delims_opt \or: opt \or:
+ e \or: E \or: prefix \or: processor \fi: :Nw
+ } #1
+ }
+ { \@@_split_end_item:n {#1} \@@_split_signature_loop:Nw }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{
+% \c_@@_show_type_t_tl,
+% \c_@@_show_type_r_tl,\c_@@_show_type_d_tl,
+% \c_@@_show_type_R_tl,\c_@@_show_type_D_tl,
+% \c_@@_show_type_O_tl,
+% \c_@@_show_type_e_tl,
+% \c_@@_show_type_E_tl,
+% \c_@@_show_type_+_tl,\c_@@_show_type_!_tl,
+% \c_@@_show_type_>_tl,
+% }
+% The token lists \cs[no-index]{c_@@_show_type_\meta{type}_tl} exist
+% for nontrivial (for printing) \meta{types} that require special
+% parsing (like delimiters or optional arguments). Values from~0 to~7
+% are assigned to each type:
+% \begin{enumerate}
+% \item a single delimiter token;
+% \item two delimiter tokens;
+% \item two delimiter tokens plus a default value;
+% \item a default value;
+% \item a list of embellishments (exclusive for |e|-type);
+% \item embellishments plus defaults (exclusive for |E|-type);
+% \item simple prefixes;
+% \item prefixes with arguments (argument processors);
+% \end{enumerate}
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1 #2
+ {
+ \quark_if_nil:nF {#1}
+ { \tl_const:cn { c_@@_show_type_#1_tl } {#2} \@@_tmp:w }
+ }
+\@@_tmp:w t0 r1 d1 R2 D2 O3 e4 E5 +6 !6 >7 \q_nil \q_nil
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_show_delim:Nw,\@@_show_delims:Nw,
+% \@@_show_delims_opt:Nw,\@@_show_opt:Nw,
+% \@@_show_e:Nw,\@@_show_E:Nw,
+% \@@_show_prefix:Nw,\@@_show_processor:Nw,
+% }
+% Now, based on each type we know how to act. In most cases it is
+% just a matter of feeding in the grabbed arguments and resuming the
+% loop. The embellishments require a bit more attention: the
+% |e|-type loops through the list of embellishments and adds each to
+% the token list as a separate argument. The |E|-type does more or
+% less the same, but uses \cs{@@_tl_mapthread_function:nnN} to map
+% over two lists simultaneously, adding each token and default to the
+% token list for printing.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_delim:Nw #1 #2
+ { \@@_split_end_item:n { #1 #2 } \@@_split_signature_loop:Nw }
+\cs_new_protected:Npn \@@_show_delims:Nw #1 #2 #3
+ { \@@_split_end_item:n { #1 #2 #3 } \@@_split_signature_loop:Nw }
+\cs_new_protected:Npn \@@_show_delims_opt:Nw #1 #2 #3 #4
+ { \@@_split_end_item:n { #1 #2 #3 {#4} } \@@_split_signature_loop:Nw }
+\cs_new_protected:Npn \@@_show_opt:Nw #1 #2
+ { \@@_split_end_item:n { #1 {#2} } \@@_split_signature_loop:Nw }
+\cs_new_protected:Npn \@@_show_e:Nw #1 #2
+ {
+ \tl_map_inline:nn {#2}
+ {
+ \@@_split_start_item:
+ \@@_split_end_item:n { #1 ##1 }
+ }
+ \@@_split_signature_loop:Nw
+ }
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new_protected:Npn \@@_show_E:Nw ##1 ##2 ##3
+ {
+ \cs_set_protected:Npn \@@_tmp:w ####1 ####2
+ {
+ \@@_split_start_item:
+ \@@_split_end_item:n { ##1 ####1 {####2} }
+ }
+ \@@_tl_mapthread_function:nnN {##2}
+ { ##3 {#1} {#1} {#1} {#1} {#1} {#1} {#1} {#1} {#1} } \@@_tmp:w
+ \@@_split_signature_loop:Nw
+ }
+ }
+\exp_args:NV \@@_tmp:w \c_novalue_tl
+% \end{macrocode}
+%
+% Minor wrinkle with the prefixes: they use \cs{@@_split_add_item:n}
+% instead of \cs{@@_split_end_item:n} (|add| \emph{vs.} |end|) because
+% they are followed by an argument, so they can't end the item.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_prefix:Nw #1
+ { \@@_split_add_item:n {#1} \@@_split_signature_loop:Nw }
+\cs_new_protected:Npn \@@_show_processor:Nw #1 #2
+ { \@@_split_add_item:n { #1 {#2} } \@@_split_signature_loop:Nw }
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_split_start_item:,
+% \@@_split_add_item:n,
+% \@@_split_end_item:n,
+% }
+% And now the auxiliaries that store the strings to be printed.
+% \cs{@@_split_start_item:} starts an item from scratch,
+% \cs{@@_split_add_item:n} adds tokens to an item without adding a
+% newline, and \cs{@@_split_end_item:n} adds tokens, terminates the
+% item with a newline, and steps the argument count.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_split_start_item:
+ {
+ \tl_set:Nx \l_@@_tmpb_tl
+ { ~ \c_space_tl \c_hash_str \int_use:N \l_@@_current_arg_int : }
+ }
+\cs_new_protected:Npn \@@_split_add_item:n #1
+ { \tl_put_right:Nx \l_@@_tmpb_tl { \tl_to_str:n {#1} } }
+\cs_new_protected:Npn \@@_split_end_item:n #1
+ {
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ { \l_@@_tmpb_tl \tl_to_str:n {#1} \iow_newline: }
+ \tl_clear:N \l_@@_tmpb_tl
+ \int_incr:N \l_@@_current_arg_int
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% Not much to do regarding \pkg{latexrelease}: we could remove the
+% entries from \cs{@showcommandlisthook}, but it doesn't seem
+% worth it.
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_show:N}%
+%<latexrelease> {Support~\ShowCommand~in~ltcmd}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
% \subsection{Grabbing arguments}
%
% All of the grabbers follow the same basic pattern. The initial
@@ -2023,6 +2733,7 @@
% \end{macro}
% \end{macro}
% \end{macro}
+%
% \begin{macro}{\@@_grab_D_nested:NNnN}
% \begin{macro}{\@@_grab_D_nested:w}
% \begin{macro}{\l_@@_nesting_a_tl}
@@ -2587,7 +3298,7 @@
\exp_after:wN \exp_after:wN \exp_after:wN
\peek_meaning_remove:NTF \char_generate:nn { \tex_endlinechar:D } { 6 }
{
- \msg_error:nnxxx { cmd } { verbatim-newline }
+ \msg_error:nnxxx { cmd } { verbatim-nl }
{ \@@_environment_or_command: }
{ \tl_to_str:N \l_@@_v_arg_tl }
{ \tl_to_str:n {#1} }
@@ -3115,7 +3826,7 @@
\ProcessedArgument
\q_stop
}
- \msg_error:nnxxx { cmd } { split-excess-tokens }
+ \msg_error:nnxxx { cmd } { arg-split }
{ \tl_to_str:n {#3} } { \int_eval:n { #2 + 1 } }
{ \tl_to_str:n {#4} }
}
@@ -3375,8 +4086,11 @@
% \end{macro}
%
% \begin{macro}{\__kernel_cmd_if_xparse:NTF}
+% \begin{macro}{\@@_cmd_type_cases:Nnnnn}
% \changes{v1.0d}{2021/04/19}{Renamed \cs{__cmd_cmd_if_xparse:NTF} to
% \cs{__kernel_cmd_if_xparse:NTF} for cross-module usage}
+% \changes{v1.0d}{2021/07/30}{Added \cs{@@_cmd_type_cases:Nnnnn} for
+% \cs{NewCommandCopy} and \cs{ShowCommand} support}
% \begin{macro}{\@@_cmd_if_xparse_aux:N}
%
% To determine whether the command is an \pkg{xparse} command check
@@ -3384,31 +4098,50 @@
% that its |replacement_spec| starts with either
% \cs{@@_start:nNNnnn} (non-expandable command) or
% \cs{@@_start_expandable:nNNNNn} (expandable command) or
-% \cs{@@_start_env:nnnnn} (environment).
+% \cs{@@_start_env:nnnnn} (environment) or
+% \cs[no-index]{environment~\#1~end~aux} (environment end).
%
% This conditional is needed in several kernel modules and is
% therefore has a kernel-internal name.
% \begin{macrocode}
-\cs_new_protected:Npn \__kernel_cmd_if_xparse:NTF #1
+\cs_new_protected:Npn \@@_cmd_type_cases:NnnnnF #1 #2 #3 #4 #5 #6
{
- \exp_args:Nf \str_case_e:nnTF
+ \exp_args:Ne \str_case_e:nnF
{
\exp_args:Nf \tl_if_empty:nT { \cs_argument_spec:N #1 }
{
- \exp_last_unbraced:Nf \@@_cmd_if_xparse_aux:w
- { \cs_replacement_spec:N #1 } ~ \q_stop
+ \token_if_macro:NT #1
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \token_to_str:N
+ \exp_after:wN \use_i_delimit_by_q_stop:nw
+ #1 \scan_stop: \q_stop
+ }
}
}
{
- { \token_to_str:N \@@_start:nNNnnn } { }
- { \token_to_str:N \@@_start_expandable:nNNNNn } { }
- { \token_to_str:N \@@_start_env:nnnnn } { }
+ { \token_to_str:N \@@_start:nNNnnn } {#2}
+ { \token_to_str:N \@@_start_expandable:nNNNNn } {#3}
+ { \token_to_str:N \@@_start_env:nnnnn } {#4}
+ {
+ \exp_after:wN \token_to_str:N
+ \cs:w environment~
+ \exp_last_unbraced:Ne \use_none:nnn
+ { \cs_to_str:N #1 } ~end~aux \cs_end:
+ } {#5}
}
+ {#6}
+ }
+\cs_new_protected:Npn \__kernel_cmd_if_xparse:NTF #1
+ {
+ \@@_cmd_type_cases:NnnnnF #1
+ { } { } { } { } { \use_iii:nnn }
+ \use_i:nn
}
-\cs_new:Npn \@@_cmd_if_xparse_aux:w #1 ~ #2 \q_stop {#1}
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\@@_peek_nonspace:NTF, \@@_peek_nonspace_remove:NTF, \@@_peek_nonspace_aux:nNNTF}
% Collect spaces in a loop, and put the collected spaces back in the
@@ -3434,7 +4167,7 @@
% token is a control sequence, also check that the \meta{csname} is
% the same as the control sequence peeked at. This extra verification
% is necessary when the command is delimited by control sequence tokens
-% (as opposed to character tokens), and we want the the exact same
+% (as opposed to character tokens), and we want the exact same
% control sequence to match.
% \begin{macrocode}
\cs_new_protected:Npn \@@_peek_meaning:NTF
@@ -3504,94 +4237,98 @@
% \end{macro}
%
% Some messages intended as errors when defining commands/environments.
+% \changes{v1.0f}{2021/06/04}{Normalize various error messages}
% \begin{macrocode}
\msg_new:nnnn { cmd } { arg-after-body }
- { In~the~definition~of~#1,~b~(body)~argument~must~be~last. }
+ { Argument~type~'b'~must~be~last~in~#1. }
{
- The~'body'~argument~type~is~followed~by~'#2'~in~the~argument~
- specification~of~the~#1.~This~is~not~allowed.
+ The~'b'~argument~type~must~come~last~but~it~is~followed~
+ by~'#2'~in~the~argument~specification.~This~is~not~allowed.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { bad-arg-spec }
{ Bad~argument~specification~'#2'~for~#1. }
{
- The~argument~specification~provided~was~not~valid:~
- one~or~more~mandatory~pieces~of~information~were~missing.
+ The~argument~specification~provided~is~not~valid:~
+ one~or~more~mandatory~parts~are~missing.
\c_@@_ignore_def_tl
}
-\msg_new:nnnn { cmd } { command-already-defined }
- { Command~'#1'~already~defined! }
+\msg_new:nnnn { cmd } { already-defined }
+ { Command~'#1'~already~defined. }
{
You~have~used~#2~
with~a~command~that~already~has~a~definition. \\ \\
The~existing~definition~of~'#1'~will~not~be~altered.
}
-\msg_new:nnnn { cmd } { command-not-yet-defined }
- { Command ~'#1'~not~yet~defined! }
+\msg_new:nnnn { cmd } { undefined }
+ { Command ~'#1'~undefined. }
{
You~have~used~#2~
with~a~command~that~was~never~defined.
\c_@@_ignore_def_tl
}
-\msg_new:nnnn { cmd } { environment-already-defined }
- { Environment~'#1'~already~defined! }
+\msg_new:nnnn { cmd } { env-already-defined }
+ { Environment~'#1'~already~defined. }
{
You~have~used~\NewDocumentEnvironment
with~an~environment~that~already~has~a~definition. \\ \\
The~existing~definition~of~'#1'~will~not~be~altered.
}
-\msg_new:nnnn { cmd } { environment-not-yet-defined }
- { Environment~'#1'~not~yet~defined! }
+\msg_new:nnnn { cmd } { env-end-already-defined }
+ { End~of~environment~'#1'~already~defined. }
+ {
+ You~have~used~\NewDocumentEnvironment
+ with~an~environment~that~already~has~a~definition~for~'end#1'. \\ \\
+ The~existing~definition~of~'#1'~will~not~be~altered.
+ }
+\msg_new:nnnn { cmd } { env-undefined }
+ { Environment~'#1'~undefined. }
{
You~have~used~\RenewDocumentEnvironment
with~an~environment~that~was~never~defined.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { expandable-ending-optional }
- {
- Argument~specification~'#2'~for~expandable~command~'#1'~
- ends~with~optional~argument.
- }
+ { Bad~argument~specification~'#2'~for~#1. }
{
Expandable~commands~must~have~a~final~mandatory~argument~
(or~no~arguments~at~all).~You~cannot~have~a~terminal~optional~
argument~with~expandable~commands.
}
-\msg_new:nnnn { cmd } { inconsistent-long }
- { Inconsistent~long~arguments~for~expandable~command~'#1'. }
+\msg_new:nnnn { cmd } { long-short-mix }
+ { Invalid~argument~prefix~'+'~in~command~'#1'. }
{
The~arguments~for~an~expandable~command~must~not~involve~short~
- arguments~after~long~arguments.~You~have~tried~to~mix~the~two~types.
+ arguments~after~long~arguments.~You~have~tried~to~mix~the~two~types~
+ when~defining~'#1'.
}
\msg_new:nnnn { cmd } { invalid-command-arg }
- { Argument~type~'#2'~not~available~for~#1. }
+ { Invalid~argument~type~'#2'~in~#1. }
{
The~letter~'#2'~can~only~be~used~in~environment~argument~
- specifications,~not~for~commands.
+ specifications,~but~not~for~commands.
\\ \\
- LaTeX~will~ignore~this~entire~definition.
+ LaTeX~will~ignore~the~entire~definition.
}
-\msg_new:nnnn { cmd } { invalid-expandable-argument-type }
- { Argument~type~'#2'~not~available~for~expandable~command~'#1'. }
+\msg_new:nnnn { cmd } { invalid-expandable-arg }
+ { Invalid~argument~type~'#2'~in~#1. }
{
The~letter~'#2'~specifies~an~argument~type~which~cannot~be~used~
in~an~expandable~command.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { invalid-after-optional-expandably }
- {
- Argument~type~'#2'~not~available~after~optional~argument~
- for~expandable~command~'#1'.
- }
+ { Argument~'#2'~invalid~after~optional~arg~in~#1. }
{
The~letter~'#2'~specifies~an~argument~type~which~cannot~be~used~
in~an~expandable~command~after~an~optional~argument.
\c_@@_ignore_def_tl
}
-\msg_new:nnnn { cmd } { non-trailing-obey-spaces }
- { Prefix~'!'~used~before~mandatory~argument~'#2'~of~#1. }
+\msg_new:nnnn { cmd } { invalid-bang }
+ { Invalid~argument~prefix~'!'~in~#1. }
{
- The~prefix~'!'~can~only~apply~to~trailing~optional~arguments.
+ The~prefix~'!'~is~only~allowed~for~trailing~optional~arguments.~
+ You~tried~to~apply~it~to~'#2'.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { not-definable }
@@ -3611,75 +4348,75 @@
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { not-single-token }
+ { Argument~delimiter~'#2'~invalid~in~#1. }
{
- Argument~delimiter~'#2'~for~the~#1~should~be~
- a~single~non-space~token.
- }
- {
- The~argument~specification~provided~was~not~valid:~in~a~place~
- where~a~single~token~is~required,~LaTeX~found~'#2'.
+ The~argument~specification~contains~
+ \tl_if_empty:nTF{#2}{nothing}{'#2'}~
+ in~a~place~
+ where~a~single~token~is~required.
\c_@@_ignore_def_tl
}
-\msg_new:nnnn { cmd } { forbidden-implicit-group-token }
- { Argument~delimiter~'#2'~for~the~#1~is~not~allowed. }
+\msg_new:nnnn { cmd } { forbidden-group-token }
+ { Argument~delimiter~'#2'~invalid~in~#1. }
{
- The~argument~specification~provided~was~not~valid:~the~implicit~
- #3-group~token~'#2'~is~not~allowed~as~an~argument~delimiter.
+ The~argument~specification~contains~the~implicit~
+ #3-group~token~'#2'~which~is~not~allowed~as~an~argument~delimiter.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { processor-in-expandable }
- { Argument~processor~'>{#2}'~cannot~be~used~for~the~expandable~command~'#1'. }
+ { Invalid~argument~prefix~'>'~in~command~'#1'. }
{
- The~argument~specification~for~#1~contains~a~processor~function:~
- this~is~only~supported~for~standard~robust~commands.
+ The~argument~specification~for~'#1'~contains~the~processor~function~'>{#2}'.~
+ This~is~only~supported~for~robust~commands,~but~not~for~expandable~ones.
\c_@@_ignore_def_tl
}
-\msg_new:nnnn { cmd } { too-many-arguments }
- { Too~many~arguments~in~argument~specification~'#2'~of~#1. }
+\msg_new:nnnn { cmd } { too-many-args }
+ { Too~many~arguments~for~#1. }
{
- The~argument~specification~provided~has~more~than~9~arguments.~
+ The~argument~specification~'#2'~asks~for~more~than~9~arguments.~
This~cannot~be~implemented.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { two-markers }
- { Two~'#2'~apply~to~the~same~argument~in~argument~specification~of~#1. }
+ { Invalid~argument~prefix~'#2'~in~#1. }
{
- The~argument~specification~provided~has~two~markers~'#2'~applying~
- to~the~same~argument;~these~are~redundant.
+ The~argument~specification~provided~for~#1~has~two~'#2'~markers~applied~
+ to~the~same~argument;~one~is~redundant.
}
-\msg_new:nnnn { cmd } { unknown-argument-type }
- { Unknown~argument~type~'#2'~for~the~#1. }
+\msg_new:nnnn { cmd } { unknown-argument-type } % should be unkown-arg-type but dep in xparse
+ { Invalid~argument~type~'#2'~in~#1. }
{
The~letter~'#2'~does~not~specify~a~known~argument~type.
\c_@@_ignore_def_tl
}
-\msg_new:nnnn { cmd } { xparse-argument-type }
- { Deprecated~argument~type~'#2'~for~the~#1~requires~xparse. }
+\msg_new:nnnn { cmd } { xparse-arg-type }
+ { Invalid~argument~type~'#2'~in~#1~(requires~xparse). }
{
- The~letter~'#2'~specifies~a~known~argument~type~that~requires~
- the~xparse~package.
+ The~letter~'#2'~specifies~a~known~but~deprecated~argument~type.~
+ If~you~really~need~it~you~have~to~load~the~xparse~package.
\c_@@_ignore_def_tl
}
% \end{macrocode}
%
% Errors when using commands/environments. The \texttt{if-boolean}
% message is always used in expandable errors. The
-% \texttt{loop-in-defaults} and \texttt{missing-required} messages can
+% \texttt{default-loop} and \texttt{missing-required} messages can
% be expandable or not expandable.
% \begin{macrocode}
\msg_new:nnn { cmd } { if-boolean }
- { Invalid~use~\iow_char:N\\IfBooleanTF~{#1} }
-\msg_new:nnnn { cmd } { loop-in-defaults }
- { Defaults~of~#1~have~circular~dependency. }
+ { Invalid~argument~{#1}~to~\iow_char:N\\IfBoolean... }
+\msg_new:nnnn { cmd } { default-loop }
+ { Circular~dependency~in~defaults~of~#1. }
{
The~default~values~of~two~or~more~arguments~of~the~#1~
depend~on~each~other~in~a~way~that~cannot~be~resolved.
}
\msg_new:nnnn { cmd } { missing-required }
- { Missing~required~argument~for~#1. }
+ { Required~argument~missing~for~#1. }
{
- The~current~#1~expects~an~argument~starting~with~'#2'.~
- LaTeX~did~not~find~it,~and~will~insert~a~default~value~to~be~processed.
+ The~#1~expects~one~of~its~arguments~to~start~with~'#2'.~
+ LaTeX~did~not~find~this~argument~and~will~insert~a~default~value~
+ for~further~processing.
}
\msg_new:nnnn { cmd } { non-xparse }
{ \str_uppercase:n #1~not~defined~using~xparse. }
@@ -3687,12 +4424,12 @@
You~have~asked~for~the~argument~specification~for~the~#1,~
but~this~was~not~defined~using~xparse.
}
-\msg_new:nnnn { cmd } { split-excess-tokens }
- { Too~many~'#1'~tokens~when~trying~to~split~argument. }
+\msg_new:nnnn { cmd } { arg-split }
+ { Too~many~'#1'~separators~in~argument. }
{
LaTeX~was~asked~to~split~the~input~'#3'~
- at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~
- There~were~too~many~'#1'~tokens.
+ at~each~occurrence~of~the~separator~'#1'~into~#2~parts.~
+ Too~many~separators~were~found.
}
\msg_new:nnnn { cmd } { unknown }
{ Unknown~document~#1. }
@@ -3700,54 +4437,62 @@
You~have~asked~for~the~argument~specification~for~the~#1,~
but~it~is~not~defined.
}
-\msg_new:nnnn { cmd } { verbatim-newline }
- { Verbatim~argument~of~#1~ended~by~end~of~line. }
+\msg_new:nnnn { cmd } { verbatim-nl }
+ { Verbatim-like~#1~ended~by~end~of~line. }
{
The~verbatim~argument~of~the~#1~cannot~contain~more~than~one~line,~
but~the~end~
of~the~current~line~has~been~reached.~You~may~have~forgotten~the~
closing~delimiter.
\\ \\
- LaTeX~will~ignore~'#2'.
+ LaTeX~will~ignore~'#2'~and~you~may~get~some~additional~
+ (low-level)~errors.
}
\msg_new:nnnn { cmd } { verbatim-tokenized }
- { The~verbatim~#1~cannot~be~used~inside~an~argument. }
+ { Verbatim-like~#1~illegal~in~argument. }
{
- The~#1~takes~a~verbatim~argument.~
- It~may~not~appear~within~the~argument~of~another~function.~
- It~received~an~illegal~token \tl_if_empty:nF {#3} { ~'#3' } .
+ The~#1~takes~a~verbatim~argument~and~should~therefore~normally~
+ not~be~used~in~arguments~of~other~commands~or~environments.~
+ LaTeX~found~an~illegal~token~ \tl_if_empty:nF {#3} { (#3)~ }
+ after~'#2'~and~will~drop~everything~up~to~this~point.
\\ \\
- LaTeX~will~ignore~'#2'.
+ Expect~further~(low-level)~errors.
}
% \end{macrocode}
%
% Intended more for information.
% \begin{macrocode}
-\msg_new:nnn { cmd } { define-command }
+\msg_new:nnn { cmd } { define-command } % should be just ``define'' but dep in xparse
{
Defining~command~#1~
with~sig.~'#2'~\msg_line_context:.
}
-\msg_new:nnn { cmd } { define-environment }
+\msg_new:nnn { cmd } { define-env }
{
Defining~environment~'#1'~
with~sig.~'#2'~\msg_line_context:.
}
-\msg_new:nnn { cmd } { redefine-command }
+\msg_new:nnn { cmd } { redefine }
{
Redefining~command~#1~
with~sig.~'#2'~\msg_line_context:.
}
-\msg_new:nnn { cmd } { redefine-environment }
+\msg_new:nnn { cmd } { redefine-env }
{
Redefining~environment~'#1'~
with~sig.~'#2'~\msg_line_context:.
}
\msg_new:nnn { cmd } { optional-mandatory }
{
- Since~the~mandatory~argument~'#1'~has~the~same~delimiter~'#2'~
- as~a~previous~optional~argument,~it~will~not~be~possible~to~
- omit~all~optional~arguments~when~calling~this~command.
+ Optional~and~mandatory~argument~with~same~delimiter~'#2'.
+ \\ \\
+ The~mandatory~argument~specified~with~
+ '\str_case:nnF{#1}{ {R/r}{r'~or~'R} }{#1}'~has~the~
+ same~delimiter~'#2'~as~an~earlier~optional~argument.~
+ It~will~therefore~not~be~possible~to~omit~all~the~earlier~
+ optional~arguments~when~calling~this~command.
+ \\ \\
+ This~may~be~intentional,~but~then~it~might~be~a~mistake.
}
\msg_new:nnn { cmd } { unsupported-let }
{
@@ -3787,7 +4532,7 @@
{
\cs_if_exist:NTF #1
{
- \msg_error:nnxx { cmd } { command-already-defined }
+ \msg_error:nnxx { cmd } { already-defined }
{ \use:nnn \token_to_str:N #1 { } }
{ \token_to_str:N \NewDocumentCommand }
}
@@ -3801,7 +4546,7 @@
\cs_if_exist:NTF #1
{ \@@_declare_cmd:Nnn #1 {#2} {#3} }
{
- \msg_error:nnxx { cmd } { command-not-yet-defined }
+ \msg_error:nnxx { cmd } { undefined }
{ \use:nnn \token_to_str:N #1 { } }
{ \token_to_str:N \RenewDocumentCommand }
}
@@ -3824,6 +4569,7 @@
% \end{macro}
%
% \begin{macro}{\NewDocumentEnvironment}
+% \changes{v1.0h}{2021/08/27}{Check for end-of-environment command}
% \begin{macro}{\RenewDocumentEnvironment}
% \begin{macro}{\ProvideDocumentEnvironment}
% \begin{macro}{\DeclareDocumentEnvironment}
@@ -3832,14 +4578,18 @@
\cs_new_protected:Npn \NewDocumentEnvironment #1#2#3#4
{
\cs_if_exist:cTF {#1}
- { \msg_error:nnx { cmd } { environment-already-defined } {#1} }
- { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
+ { \msg_error:nnx { cmd } { env-already-defined } {#1} }
+ {
+ \cs_if_exist:cTF { end #1 }
+ { \msg_error:nnx { cmd } { env-end-already-defined } {#1} }
+ { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
+ }
}
\cs_new_protected:Npn \RenewDocumentEnvironment #1#2#3#4
{
\cs_if_exist:cTF {#1}
{ \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
- { \msg_error:nnx { cmd } { environment-not-yet-defined } {#1} }
+ { \msg_error:nnx { cmd } { env-undefined } {#1} }
}
\cs_new_protected:Npn \ProvideDocumentEnvironment #1#2#3#4
{ \cs_if_exist:cF {#1} { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} } }
@@ -3866,7 +4616,7 @@
{
\cs_if_exist:NTF #1
{
- \msg_error:nnxx { cmd } { command-already-defined }
+ \msg_error:nnxx { cmd } { already-defined }
{ \use:nnn \token_to_str:N #1 { } }
{ \token_to_str:N \NewExpandableDocumentCommand }
}
@@ -3880,7 +4630,7 @@
\cs_if_exist:NTF #1
{ \@@_declare_expandable_cmd:Nnn #1 {#2} {#3} }
{
- \msg_error:nnxx { cmd } { command-not-yet-defined }
+ \msg_error:nnxx { cmd } { undefined }
{ \use:nnn \token_to_str:N #1 { } }
{ \token_to_str:N \RenewExpandableDocumentCommand }
}
@@ -4032,3 +4782,4 @@
% \end{macrocode}
%
% \Finale
+
diff --git a/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx b/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx
index 40cd55e52c7..208f7c3d22c 100644
--- a/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx
+++ b/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx
@@ -13,21 +13,14 @@
%
%%% From File: ltcmdhooks.dtx
%
-\def\ltcmdhooksversion{v1.0b}
-\def\ltcmdhooksdate{2021/05/26}
+\def\ltcmdhooksversion{v1.0f}
+\def\ltcmdhooksdate{2021/10/20}
%
%
%
%<*driver>
\documentclass{l3doc}
%\usepackage{ltcmdhooks}
-\makeatletter
-\providecommand\footref[1]{%
- \begingroup
- \unrestored@protected@xdef\@thefnmark{\ref{#1}}%
- \endgroup
- \@footnotemark}
-\makeatother
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -360,19 +353,46 @@
% \end{macro}
%
% \begin{macro}{\l_@@_patch_prefixes_tl}
-% \begin{macro}{\l_@@_patch_param_text_tl}
-% \begin{macro}{\l_@@_patch_replacement_tl}
+% \begin{macro}{\l_@@_param_text_tl}
+% \begin{macro}{\l_@@_replace_text_tl}
% The prefixes and parameters of the definition for the macro being
% patched.
% \begin{macrocode}
\tl_new:N \l_@@_patch_prefixes_tl
-\tl_new:N \l_@@_patch_param_text_tl
-\tl_new:N \l_@@_patch_replacement_tl
+\tl_new:N \l_@@_param_text_tl
+\tl_new:N \l_@@_replace_text_tl
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\c_@@_hash_tl}
+% A constant token list that contains two parameter tokens.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_hash_tl { # # }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_exp_not:NN}
+% \begin{macro}{\@@_def_cmd:w}
+% Two temporary macros that change depending on the macro being
+% patched.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_exp_not:NN ?
+\cs_new_eq:NN \@@_def_cmd:w ?
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\q_@@_recursion_tail,\q_@@_recursion_stop}
+% Internal quarks for recursion: they can't appear in any macro being
+% patched.
+% \begin{macrocode}
+\quark_new:N \q_@@_recursion_tail
+\quark_new:N \q_@@_recursion_stop
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\g_@@_delayed_patches_prop}
% A list containing the patches delayed to |\begin{document}|, so that
% patching is not attempted twice.
@@ -400,24 +420,44 @@
%
% \subsection{Patching or delaying}
%
-% \begin{macro}{\@@_try_put_cmd_hook:n,\@@_try_put_cmd_hook:w}
% Before |\begin{document}| all patching is delayed.
+%
+% \begin{macro}{\@@_try_put_cmd_hook:n,\@@_try_put_cmd_hook:w}
% This function is called from within \cs{AddToHook}, when code is
-% added to a generic |cmd| hook is newly declared. It checks whether
-% the patch position is valid, then proceeds to trying to patch or
-% delaying to |\begin{document}| if in the preamble.
+% first added to a generic |cmd| hook.
+% If it is called within in the preamble, it delays the action
+% until |\begin{document}|;
+% otherwise it tries to update the hook.
+% \changes{v1.0d}{2021/08/25}{Simplify generic hook detection}
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_put_cmd_hook:n}%
+%<latexrelease> {Standardise~generic~hook~names}
\cs_new_protected:Npn \@@_try_put_cmd_hook:n #1
{ \@@_try_put_cmd_hook:w #1 / / / \s_@@_mark {#1} }
\cs_new_protected:Npn \@@_try_put_cmd_hook:w
#1 / #2 / #3 / #4 \s_@@_mark #5
{
\@@_debug:n { \iow_term:n { ->~Adding~cmd~hook~to~'#2'~(#3): } }
- \str_case:nnTF {#3}
- { { before } { } { after } { } }
- { \exp_args:Nc \@@_patch_cmd_or_delay:Nnn {#2} {#2} {#3} }
- { \msg_error:nnnn { hooks } { wrong-cmd-hook } {#2} {#3} }
+ \exp_args:Nc \@@_patch_cmd_or_delay:Nnn {#2} {#2} {#3}
}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_try_put_cmd_hook:n}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\cs_new_protected:Npn \@@_try_put_cmd_hook:n #1
+%<latexrelease> { \@@_try_put_cmd_hook:w #1 / / / \s_@@_mark {#1} }
+%<latexrelease>\cs_new_protected:Npn \@@_try_put_cmd_hook:w
+%<latexrelease> #1 / #2 / #3 / #4 \s_@@_mark #5
+%<latexrelease> {
+%<latexrelease> \@@_debug:n { \iow_term:n { ->~Adding~cmd~hook~to~'#2'~(#3): } }
+%<latexrelease> \str_case:nnTF {#3}
+%<latexrelease> { { before } { } { after } { } }
+%<latexrelease> { \exp_args:Nc \@@_patch_cmd_or_delay:Nnn {#2} {#2} {#3} }
+%<latexrelease> { \msg_error:nnnn { hooks } { wrong-cmd-hook } {#2} {#3} }
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
@@ -592,17 +632,28 @@
%
% With \cs{@@_patch_DeclareRobustCommand:Nnn} we check if the command
% has an optional argument (with a test counter-intuitively called
-% \tn{@if@newcommand}). If so, we forward the action to
-% \cs{@@_patch_newcommand:Nnn}, otherwise call the patching engine
+% \tn{@if@newcommand}; also make sure the command doesn't take args by
+% calling \cs{robust@command@chk@safe}). If so, we pass the patching action
+% to \cs{@@_patch_newcommand:Nnn}, otherwise we call the patching engine
% \cs{@@_patch_expand_redefine:NNnn} with a \cs{c_false_bool} to
% indicate that there is no optional argument.
+%
+% \changes{v1.0c}{2021/07/20}
+% {Use \cs{robust@command@chk@safe} before \cs{@if@newcommand}.}
% \begin{macrocode}
\cs_new_protected:Npn \@@_patch_DeclareRobustCommand:Nnn #1
{
- \exp_args:Nc \@if@newcommand { \cs_to_str:N #1 ~ }
- { \exp_args:Nc \@@_patch_newcommand:Nnn }
- { \exp_args:NNc \@@_patch_expand_redefine:NNnn \c_false_bool }
- { \cs_to_str:N #1 ~ }
+ \exp_args:Nc \@@_patch_DeclareRobustCommand_aux:Nnn
+ { \cs_to_str:N #1 ~ }
+ }
+\cs_new_protected:Npn \@@_patch_DeclareRobustCommand_aux:Nnn #1
+ {
+ \robust@command@chk@safe #1
+ { \@if@newcommand #1 }
+ { \use_ii:nn }
+ { \@@_patch_newcommand:Nnn }
+ { \@@_patch_expand_redefine:NNnn \c_false_bool }
+ #1
}
% \end{macrocode}
% \end{macro}
@@ -639,13 +690,71 @@
%
%
%
+%
% \begin{macro}{\@@_patch_expand_redefine:NNnn}
+% \begin{macro}{\@@_redefine_with_hooks:Nnnn}
% \begin{macro}[EXP]{\@@_make_prefixes:w}
% Now the real action begins. Here we have in |#1| a boolean
-% indicating if the command has a |[|\ldots|]|-delimited argument, in
-% |#2| the command control sequence, in |#3| the name of the command
-% (note that |#1|${}\ne{}$|\csname#2\endcsname| at this point!), and
-% in |#4| the hook position, either |before| or |after|.
+% indicating if the command has a leading |[|\ldots|]|-delimited
+% argument, in |#2| the command control sequence, in |#3| the name of
+% the command (note that |#1|${}\ne{}$|\csname#2\endcsname| at this
+% point!), and in |#4| the hook position, either |before| or |after|.
+%
+% \changes{v1.0f}{2021/10/20}
+% {Correct patching by expansion+redefinition when the macro
+% contains a parameter tokens (gh/697).}
+% Patching with expansion+redefinition is trickier than it looks like
+% at first glance. Suppose the simple definition:
+% \begin{verbatim}
+% \def\foo#1{#1##2}
+% \end{verbatim}
+% When defined, its \meta{replacement text} will be a token list
+% containing:
+% \begin{quote}
+% \itshape
+% out\_param |1|, mac\_param |#|, character |2|
+% \end{quote}
+%
+% Then, after expanding \cs{foo}|{##1}| (here |##| denotes a single
+% |#|$_6$) we end up with a token list with \textit{out\_param}~|1|
+% replaced:
+% \begin{quote}
+% \itshape
+% mac\_param |#|, character |1|, mac\_param |#|, character |2|
+% \end{quote}
+% that is, the definition would be:
+% \begin{verbatim}
+% \def\foo#1{#1#2}
+% \end{verbatim}
+% which obviously fails, because the original input in the definition
+% was |##| but \TeX{} reduced that to a single parameter token |#|$_6$
+% when carrying out the definition. That leaves no room for a clever
+% solution with (say) \cs{unexpanded}, because anything that would
+% double the second |#|$_6$, would also (incorrectly) double the
+% first, so there's not much to do other than a manual solution.
+%
+% There are three cases we can distinguish to make things hopefully
+% faster on simpler cases:
+% \begin{enumerate}
+% \item a macro with no parameters;
+% \item a macro with no parameter tokens in its definition;
+% \item a macro with parameters \emph{and} parameter tokens.
+% \end{enumerate}
+%
+% The first case is trivial: if the macro has no parameters, we can
+% just use \cs{unexpanded} around it, and if there is a parameter
+% token in it, it is handled correctly (the macro can be treated as a
+% |tl| variable).
+%
+% The second case requires looking at the \meta{replacement text} of
+% the macro to see if it has a parameter token in there. If it does
+% not, then there is no worry, and the macro can be redefined normally
+% (without \cs{unexpanded}).
+%
+% The third case, as usual, is the devious one. Here we'll have to
+% loop through the definition token by token, and double every
+% parameter token, so that this case can be handled like the previous
+% one.
% \begin{macrocode}
\cs_new_protected:Npn \@@_patch_expand_redefine:NNnn #1 #2 #3 #4
{
@@ -665,36 +774,93 @@
% \end{macrocode}
% Now build two token lists:
% \begin{description}
-% \item[\cs{l_@@_patch_param_text_tl}] will contain the
+% \item[\cs{l_@@_param_text_tl}] will contain the
% \meta{parameter text} to be used when redefining the macro. It
% should be identical to the \meta{parameter text} used when
% originally defining that macro.
-% \item[\cs{l_@@_patch_replacement_tl}] will contain braced pairs of
-% |#|$_{12}$\meta{num} to feed to the macro when expanded. This
-% token list as well as the previous will have the first item
+% \item[\cs{l_@@_replace_text_tl}] will contain braced pairs of
+% \cs{c_@@_hash_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
+% parameters in the macro from parameter tokens in the original
+% definition of the macro. Later on, \cs{c_@@_hash_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 }
{
- \tl_set:Nx \l_@@_patch_param_text_tl
- { \bool_if:NTF #1 { [####1] } { ####1 } }
- \tl_set:Nx \l_@@_patch_replacement_tl
- { \bool_if:NTF #1 { [####1] } { {####1} } }
+% \end{macrocode}
+% 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{@@_if_has_hash:nTF} to avoid testing twice (the test can be
+% rather slow).
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpa_tl { \bool_if:NTF #1 { [ ] } { { } } }
\int_step_inline:nnn { 2 } { \l_@@_patch_num_args_int }
+ { \tl_put_right:Nn \l_@@_tmpa_tl { { } } }
+ \exp_args:NNo \exp_args:No \@@_if_has_hash:nTF
+ { \exp_after:wN #2 \l_@@_tmpa_tl }
+ { \cs_set_eq:NN \@@_exp_not:n \exp_not:n }
+ { \cs_set_eq:NN \@@_exp_not:n \use:n }
+ \cs_set_protected:Npn \@@_tmp:w ##1 ##2
{
- \tl_put_right:Nn \l_@@_patch_param_text_tl { ## ####1 }
- \tl_put_right:Nn \l_@@_patch_replacement_tl { { ## ####1 } }
+ ##1 \l_@@_param_text_tl { \use:n ##2 }
+ ##1 \l_@@_replace_text_tl { \@@_exp_not:n {##2} }
}
+% \end{macrocode}
+% Here we'll conditionally add |[|\ldots|]| around the first
+% parameter:
+% \begin{macrocode}
+ \bool_if:NTF #1
+ { \@@_tmp:w \tl_set:Nx { [ \c_@@_hash_tl 1 ] } }
+ { \@@_tmp:w \tl_set:Nx { { \c_@@_hash_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 } } }
+% \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 |#|:
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_replace_text_tl
+ { \exp_not:N #2 \exp_not:V \l_@@_replace_text_tl }
+ \tl_set:Nx \l_@@_replace_text_tl
+ {
+ \token_if_eq_meaning:NNTF \@@_exp_not:n \exp_not:n
+ { \exp_args:NNV \exp_args:No \@@_double_hashes:n }
+ { \exp_args:NV \exp_not:o }
+ \l_@@_replace_text_tl
+ }
+% \end{macrocode}
+% And now, set a few auxiliaries for the case that the macro has
+% parameters, so it won't be passed through \cs{unexpanded} (twice):
+% \begin{macrocode}
+ \cs_set_eq:NN \@@_def_cmd:w \tex_gdef:D
+ \cs_set_eq:NN \@@_exp_not:NN \prg_do_nothing:
}
{
- \tl_clear:N \l_@@_patch_param_text_tl
- \tl_clear:N \l_@@_patch_replacement_tl
+% \end{macrocode}
+% In the case the macro has no parameters, we'll treat it as a token
+% list and things are much simpler (expansion control looks a bit
+% complicated, but it's just a pair of \cs{exp_not:N} preventing
+% another \cs{exp_not:n} from expanding):
+% \begin{macrocode}
+ \tl_clear:N \l_@@_param_text_tl
+ \tl_set_eq:NN \l_@@_replace_text_tl #2
+ \cs_set_eq:NN \@@_def_cmd:w \tex_xdef:D
+ \cs_set:Npn \@@_exp_not:NN ##1 { \exp_not:N ##1 \exp_not:N }
}
% \end{macrocode}
-% Finally, before redefining, we need to also get the prefixes used
-% when defining the command. Here we ensure that the \tn{escapechar}
-% is printable, otherwise a macro defined with prefixes
+% Before redefining, we need to also get the prefixes used when
+% defining the command. Here we ensure that the \tn{escapechar} is
+% printable, otherwise a macro defined with prefixes
% |\protected \long| will have it \tn{meaning} printed as
% |protectedlong|, making life unnecessarily complicated. Here the
% \tn{escapechar} is changed to |/|, then we loop between pairs of
@@ -709,34 +875,47 @@
{ \exp_not:N \@@_make_prefixes:w \cs_prefix_spec:N #2 / / }
}
% \end{macrocode}
-% Now that all the needed tools are ready, without further ado we'll
-% redefine the command |#2|. The definition uses the prefixes
-% gathered in \cs{l_@@_patch_prefixes_tl}, a primitive \cs{tex_def:D}
-% to avoid adding extra prefixes, and the \meta{parameter text} from
-% \cs{l_@@_patch_param_text_tl}.
-%
-% Then finally, in the body of the definition, we insert
-% \hook{cmd/\#3/before} if |#4| is |before|, the code of the
-% command expanded once grabbing the parameters in
-% \cs{l_@@_patch_replacement_tl}, and \hook{cmd/\#3/after} if |#4| is
-% |after|.
+% Finally, call \cs{@@_redefine_with_hooks:Nnnn} with the macro being
+% redefined in |#1|, then \cs{UseHook}|{cmd/<name>/before}| in |#2| or
+% \cs{UseHook}|{cmd/<name>/after}| in |#3| (one is always empty), and
+% in |#4| the \meta{replacement text} of the macro.
% \begin{macrocode}
\use:x
{
- \l_@@_patch_prefixes_tl \tex_def:D
- \exp_not:N #2 \exp_not:V \l_@@_patch_param_text_tl
- {
- \str_if_eq:nnT {#4} { before }
- { \exp_not:N \UseHook { cmd / #3 / #4 } }
- \exp_args:No \exp_not:o
- { \exp_after:wN #2 \l_@@_patch_replacement_tl }
- \str_if_eq:nnT {#4} { after }
- { \exp_not:N \UseHook { cmd / #3 / #4 } }
- }
+ \@@_redefine_with_hooks:Nnnn \exp_not:N #2
+ \str_if_eq:nnTF {#4} { after }
+ { \use_ii_i:nn }
+ { \use:nn }
+ { { \@@_exp_not:NN \exp_not:N \UseHook { cmd / #3 / #4 } } }
+ { { } }
+ { \@@_exp_not:NN \exp_not:V \l_@@_replace_text_tl }
}
}
% \end{macrocode}
%
+% Now that all the needed tools are ready, without further ado we'll
+% redefine the command. The definition uses the prefixes gathered in
+% \cs{l_@@_patch_prefixes_tl}, a primitive \cs{@@_def_cmd:w} (which is
+% \cs{tex_gdef:D} or \cs{tex_xdef:D}) to avoid adding extra prefixes,
+% and the \meta{parameter text} from \cs{l_@@_param_text_tl}.
+%
+% Then finally, in the body of the definition, we insert |#2|, which
+% is \hook{cmd/\#1/before} or empty, |#4| which is the
+% \meta{replacement text}, and |#3| which is \hook{cmd/\#1/after} or
+% empty.
+%
+% \changes{v1.0e}{2021/09/28}
+% {Make patching of commands a global operation (gh/674)}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_redefine_with_hooks:Nnnn #1 #2 #3 #4
+ {
+ \l_@@_patch_prefixes_tl
+ \exp_after:wN \@@_def_cmd:w
+ \exp_after:wN #1 \l_@@_param_text_tl
+ { #2 #4 #3 }
+ }
+% \end{macrocode}
+%
% Here's the auxiliary that makes the prefix control sequences for the
% redefinition. Each item has to be \cs{tl_trim_spaces:n}'d because
% the last item (and not any other) has a trailing space.
@@ -752,11 +931,125 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
%
+% Here are some auxiliaries for the contraption above.
%
+% \begin{macro}[pTF]{\@@_if_has_hash:n}
+% \begin{macro}{\@@_if_has_hash:w,\@@_if_has_hash_check:w}
+% \cs{@@_if_has_hash:nTF} searches the token list |#1| for a catcode~6
+% token, and if any is found, it returns |true|, and |false|
+% otherwise. The searching doesn't care about preserving groups or
+% spaces: we can ignore those safely (braces are removed) so that
+% searching is as fast as possible.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_has_hash:n #1 { TF }
+ { \@@_if_has_hash:w #1 ## \s_@@_mark }
+\cs_new:Npn \@@_if_has_hash:w #1
+ {
+ \tl_if_single_token:nTF {#1}
+ {
+ \token_if_eq_catcode:NNTF ## #1
+ { \@@_if_has_hash_check:w }
+ { \@@_if_has_hash:w }
+ }
+ { \@@_if_has_hash:w #1 }
+ }
+\cs_new:Npn \@@_if_has_hash_check:w #1 \s_@@_mark
+ { \tl_if_empty:nTF {#1} { \prg_return_false: } { \prg_return_true: } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
%
%
+% \begin{macro}[rEXP]{\@@_double_hashes:n}
+% \begin{macro}[rEXP]{
+% \@@_double_hashes:w,
+% \@@_double_hashes_output:N,
+% \@@_double_hashes_stop:w,
+% \@@_double_hashes_group:n,
+% \@@_double_hashes_space:w,
+% }
+% \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{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
+% (\emph{maybe} it could be done using something along the lines of
+% \url{https://tex.stackexchange.com/a/527538}, but it's far too much
+% work for close to zero benefit).
+%
+% \cs{@@_double_hashes:w} is the tail-recursive loop macro, that tests
+% which of the three types of item is in the head of the token list.
+% \begin{macrocode}
+\cs_new:Npn \@@_double_hashes:n #1
+ { \@@_double_hashes:w #1 \q_@@_recursion_tail \q_@@_recursion_stop }
+\cs_new:Npn \@@_double_hashes:w #1 \q_@@_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#1}
+ { \@@_double_hashes_output:N }
+ {
+ \tl_if_head_is_group:nTF {#1}
+ { \@@_double_hashes_group:n }
+ { \@@_double_hashes_space:w }
+ }
+ #1 \q_@@_recursion_stop
+ }
+% \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
+% it.
+% \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
+% \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}.)
+% \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,
+% and if so, leave it doubled in \cs{exp_not:n} and consume the
+% following |\exp_not:N #1|.
+% \begin{macrocode}
+ \if_catcode:w ## \exp_not:N #1
+ \exp_after:wN \use_ii:nnnn
+ \fi:
+ \use_none:n
+ { \exp_not:n { #1 #1 } }
+ }
+% \end{macrocode}
+% If both previous tests returned |false|, then leave the token
+% unexpanded and resume the loop.
+% \begin{macrocode}
+ \exp_not:N #1
+ \@@_double_hashes:w
+ }
+\cs_new:Npn \@@_double_hashes_stop:w #1 \q_@@_recursion_stop { \fi: }
+% \end{macrocode}
+%
+% Dealing with spaces and grouped tokens is trivial:
+% \begin{macrocode}
+\cs_new:Npn \@@_double_hashes_group:n #1
+ { { \@@_double_hashes:n {#1} } \@@_double_hashes:w }
+\exp_last_unbraced:NNo
+\cs_new:Npn \@@_double_hashes_space:w \c_space_tl
+ { ~ \@@_double_hashes:w }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
%
% \subsubsection{Patching by retokenization}
%
@@ -1030,8 +1323,11 @@
% \end{macrocode}
% And to close, copy the newly-defined command into the old name and
% the patching is finally completed:
+%
+% \changes{v1.0e}{2021/09/28}
+% {Make patching of commands a global operation (gh/674)}
% \begin{macrocode}
- \cs_set_eq:NN #1 \kerneltmpDoNotUse
+ \cs_gset_eq:NN #1 \kerneltmpDoNotUse
}
% \end{macrocode}
% \end{macro}
@@ -1039,15 +1335,21 @@
% \subsection{Messages}
%
% \begin{macrocode}
-\msg_new:nnnn { hooks } { wrong-cmd-hook }
- {
- Generic~hook~`cmd/#1/#2'~is~invalid.
-% The~hook~should~be~`cmd/#1/before'~or~`cmd/#1/after'.
- }
- {
- You~tried~to~add~a~generic~hook~to~command~\iow_char:N \\#1,~but~`#2'~
- is~an~invalid~component.~Only~`before'~or~`after'~are~allowed.
- }
+%<latexrelease>\IncludeInRelease{2021/11/15}{wrong-cmd-hook}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2021/11/15}{wrong-cmd-hook}%
+%<latexrelease> {Standardise~generic~hook~names}
+%<latexrelease>\msg_new:nnnn { hooks } { wrong-cmd-hook }
+%<latexrelease> {
+%<latexrelease> Generic~hook~`cmd/#1/#2'~is~invalid.
+%<latexrelease>% The~hook~should~be~`cmd/#1/before'~or~`cmd/#1/after'.
+%<latexrelease> }
+%<latexrelease> {
+%<latexrelease> You~tried~to~add~a~generic~hook~to~command~\iow_char:N \\#1,~but~`#2'~
+%<latexrelease> is~an~invalid~component.~Only~`before'~or~`after'~are~allowed.
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
\msg_new:nnnn { hooks } { cant-patch }
{
Generic~hooks~cannot~be~added~to~'#1'.
diff --git a/Master/texmf-dist/source/latex/base/ltcounts.dtx b/Master/texmf-dist/source/latex/base/ltcounts.dtx
index 445cac2f2e4..39fb47728d3 100644
--- a/Master/texmf-dist/source/latex/base/ltcounts.dtx
+++ b/Master/texmf-dist/source/latex/base/ltcounts.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltcounts.dtx}
- [2020/12/04 v1.1l LaTeX Kernel (Counters)]
+ [2021/07/08 v1.1m LaTeX Kernel (Counters)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltcounts.dtx}
@@ -106,20 +106,22 @@
%
%
% \DescribeMacro\counterwithin
-% |\counterwithin|\marg{counter}\marg{within-counter}:
+% |\counterwithin|\oarg{format}\marg{counter}\marg{within-counter}:
% Resets \meta{counter} whenever
% \meta{within-counter} is stepped. Also
% redefines |\the|\meta{counter} command to produce
-% |\the|\meta{within-counter}|.\arabic|\marg{counter}.
+% |\the|\meta{within-counter}.\meta{format}\marg{counter} with \cs{arabic} as
+% the default for \meta{format}.
% Star form omits redefining the print representation.
%
% \DescribeMacro\counterwithout
-% |\counterwithout|\marg{counter}\marg{within-counter}:
+% |\counterwithout|\oarg{format}\marg{counter}\marg{within-counter}:
% Removes \meta{counter} from the reset list of \meta{within-counter}.
% Also
% redefines |\the|\meta{counter} command to produce
-% |\arabic|\marg{counter}.
+% \meta{format}\marg{counter} with \cs{arabic} as
+% the default for \meta{format}.
% Star form omits redefining the print representation.
%
% \StopEventually{}
@@ -371,67 +373,94 @@
#3}}}
% \end{macrocode}
% \end{macro}
-
-
-% \begin{macro}{\counterwithout}
%
-% \changes{v1.1k}{2018/03/08}{Interface added}
% \begin{macrocode}
-\def\counterwithout {\@ifstar\counterwithout@s\counterwithout@x}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000-00-00}
+%<latexrelease> {\@removefromreset}{Add interfaces}%
+%<latexrelease>\let \@removefromreset \undefined
+%<latexrelease>\let \@ifbothcounters \undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
%
-% \begin{macrocode}
-\def\counterwithout@s#1#2{%
- \@ifbothcounters{#1}{#2}{\@removefromreset{#1}{#2}}}
-% \end{macrocode}
%
-% \begin{macrocode}
-\def\counterwithout@x#1#2{%
- \@ifbothcounters{#1}{#2}%
- {\@removefromreset{#1}{#2}%
- \expandafter
- \gdef\csname the#1\expandafter\endcsname\expandafter
- {\expandafter
- \@arabic\csname c@#1\endcsname}}}
-% \end{macrocode}
-% \end{macro}
-
-
-
-% \begin{macro}{\counterwithin}
%
-% \changes{v1.1k}{2018/03/08}{Interface added}
+%
+% \begin{macro}{\counterwithout,\counterwithin}
+% New implementation using xparse and supporting an optional
+% format argument.
+% \changes{v1.1m}{2021/07/08}{New implementation for
+% \cs{counterwithout} and \cs{counterwithin}}
% \begin{macrocode}
-\def\counterwithin{\@ifstar\counterwithin@s\counterwithin@x}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\counterwithout}{counter without/within}%
% \end{macrocode}
%
% \begin{macrocode}
-\def\counterwithin@s#1#2{%
- \@ifbothcounters{#1}{#2}{\@addtoreset{#1}{#2}}}
+\NewDocumentCommand \counterwithout {sO{\arabic}mm}{%
+ \@ifbothcounters{#3}{#4}{%
+ \@removefromreset{#3}{#4}%
+ \IfBooleanF #1%
+ {\expandafter
+ \gdef\csname the#3\endcsname {#2{#3}}}%
+ }%
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewDocumentCommand \counterwithin {sO{\arabic}mm}{%
+ \@ifbothcounters{#3}{#4}{%
+ \@addtoreset{#3}{#4}%
+ \IfBooleanF #1%
+ {\expandafter
+ \gdef\csname the#3\expandafter\endcsname
+ \expandafter
+ {\csname the#4\endcsname .#2{#3}}}%
+ }%
+}
% \end{macrocode}
%
-% \changes{v1.1l}{2018/04/11}{Correct default (issue/38)}
+% \changes{v1.1k}{2018/03/08}{Interface added}
% \begin{macrocode}
-\def\counterwithin@x#1#2{%
- \@ifbothcounters{#1}{#2}%
- {\@addtoreset{#1}{#2}%
- \expandafter
- \gdef\csname the#1\expandafter\endcsname\expandafter
- {\csname the#2\expandafter\endcsname\expandafter
- .\expandafter
- \@arabic\csname c@#1\endcsname}}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2018-04-01}
+%<latexrelease> {\counterwithout}{counter without/within}%
+%<latexrelease>
+%<latexrelease>\def\counterwithout {\@ifstar\counterwithout@s\counterwithout@x}
+%<latexrelease>\def\counterwithout@s#1#2{%
+%<latexrelease> \@ifbothcounters{#1}{#2}{\@removefromreset{#1}{#2}}}
+%<latexrelease>\def\counterwithout@x#1#2{%
+%<latexrelease> \@ifbothcounters{#1}{#2}%
+%<latexrelease> {\@removefromreset{#1}{#2}%
+%<latexrelease> \expandafter
+%<latexrelease> \gdef\csname the#1\expandafter\endcsname\expandafter
+%<latexrelease> {\expandafter
+%<latexrelease> \@arabic\csname c@#1\endcsname}}}
+%<latexrelease>
+%<latexrelease>\def\counterwithin{\@ifstar\counterwithin@s\counterwithin@x}
+%<latexrelease>\def\counterwithin@s#1#2{%
+%<latexrelease> \@ifbothcounters{#1}{#2}{\@addtoreset{#1}{#2}}}
% \end{macrocode}
-% \end{macro}
-
-
%
+% \changes{v1.1l}{2018/04/11}{Correct default (issue/38)}
% \begin{macrocode}
-%</2ekernel|latexrelease>
+%<latexrelease>\def\counterwithin@x#1#2{%
+%<latexrelease> \@ifbothcounters{#1}{#2}%
+%<latexrelease> {\@addtoreset{#1}{#2}%
+%<latexrelease> \expandafter
+%<latexrelease> \gdef\csname the#1\expandafter\endcsname\expandafter
+%<latexrelease> {\csname the#2\expandafter\endcsname\expandafter
+%<latexrelease> .\expandafter
+%<latexrelease> \@arabic\csname c@#1\endcsname}}}
+%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000-00-00}
-%<latexrelease> {\@removefromreset}{Add interfaces}%
-%<latexrelease>\let \@removefromreset \undefined
-%<latexrelease>\let \@ifbothcounters \undefined
+%<latexrelease> {\counterwithout}{counter without/within}%
%<latexrelease>\let \counterwithout \undefined
%<latexrelease>\let \counterwithout@s \undefined
%<latexrelease>\let \counterwithout@x \undefined
@@ -441,6 +470,9 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
+% \end{macro}
+%
+%
%
%
% Numbering commands for definitions of |\theCOUNTER| and |\list|
@@ -596,7 +628,7 @@
% recommended) this unfortunate side effect is not present.
% \begin{macrocode}
%</2ekernel>
-%<latexrelease>\IncludeInRelease{2015/01/01}{\@fnsymbol}{Use \TexOrMath}%
+%<latexrelease>\IncludeInRelease{2015/01/01}{\@fnsymbol}{Use \TextOrMath}%
%<*2ekernel|latexrelease>
\def\@fnsymbol#1{%
\ifcase#1\or \TextOrMath\textasteriskcentered *\or
@@ -612,7 +644,7 @@
}%
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
-%<latexrelease>\IncludeInRelease{0000/00/00}{\@fnsymbol}{Use \TexOrMath}%
+%<latexrelease>\IncludeInRelease{0000/00/00}{\@fnsymbol}{Use \TextOrMath}%
%<latexrelease>\def\@fnsymbol#1{\ensuremath{%
%<latexrelease> \ifcase#1\or *\or \dagger\or \ddagger\or \mathsection\or
%<latexrelease> \mathparagraph\or \|\or **\or \dagger\dagger
diff --git a/Master/texmf-dist/source/latex/base/ltdefns.dtx b/Master/texmf-dist/source/latex/base/ltdefns.dtx
index 4f39d922cce..6c85ca915d2 100644
--- a/Master/texmf-dist/source/latex/base/ltdefns.dtx
+++ b/Master/texmf-dist/source/latex/base/ltdefns.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltdefns.dtx}
- [2021/05/27 v1.5p LaTeX Kernel (definition commands)]
+ [2021/06/04 v1.5q LaTeX Kernel (definition commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdefns.dtx}
@@ -1231,7 +1231,7 @@
\count@=\escapechar
\escapechar=`\\
\@ifundefined{\expandafter\@gobble\string#1}{%
- \@latex@error{Command `\string#1' is undefined!%
+ \@latex@error{Command `\string#1' undefined.%
\MessageBreak There is nothing here to make robust}%
\@eha
}%
diff --git a/Master/texmf-dist/source/latex/base/lterror.dtx b/Master/texmf-dist/source/latex/base/lterror.dtx
index 7f480a0171f..10d93a1dbd1 100644
--- a/Master/texmf-dist/source/latex/base/lterror.dtx
+++ b/Master/texmf-dist/source/latex/base/lterror.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{lterror.dtx}
- [2019/08/30 v1.2q LaTeX Kernel (errors)]
+ [2021/08/20 v1.2t LaTeX Kernel (errors)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{lterror.dtx}
@@ -375,6 +375,58 @@ Type H <return> for immediate help.}%
% \end{macro}
% \end{macro}
%
+%
+%
+% \begin{macro}{\ClassNote,\ClassNoteNoLine,
+% \PackageNote,\PackageNoteNoLine}
+%
+% \changes{v1.2s}{2021/07/11}{Provide \cs{ClassNote} and \cs{PackageNote}}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\ClassNote}{Notes for classes/packages}%
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\ClassNote#1#2{%
+ \GenericWarning{%
+ (#1) \space\space\@spaces\@spaces
+ }{%
+ Class #1 Info: #2%
+ }%
+}
+\def\ClassNoteNoLine#1#2{\ClassNote{#1}{#2\@gobble}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\PackageNote#1#2{%
+ \GenericWarning{%
+ (#1) \@spaces\@spaces\@spaces
+ }{%
+ Package #1 Info: #2%
+ }%
+}
+\def\PackageNoteNoLine#1#2{\PackageNote{#1}{#2\@gobble}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+% We don't roll back, because if this code is used by packages then
+% most often they will not have rollback code implemented, so they
+% would immediately break even if they otherwise would work fine.
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\ClassNote}{Notes for classes/packages}%
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
% \begin{macro}{\@latex@error}
% \begin{macro}{\@latex@warning}
% \begin{macro}{\@latex@warning@no@line}
@@ -446,6 +498,50 @@ Type H <return> for immediate help.}%
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\@latex@note}
+% \begin{macro}{\@latex@note@no@line}
+% These are ``info'' messages that display on the terminal not
+% just in the transcript.
+% \changes{v1.2r}{2021/06/09}{Macros added}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\@latex@note}{Display notes}%
+\def\@latex@note#1{%
+ \GenericWarning{%
+ \@spaces\@spaces\@spaces
+ }{%
+ LaTeX Info: #1%
+ }%
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\@latex@note@no@line#1{%
+ \@latex@note{#1\@gobble}}
+% \end{macrocode}
+%
+% We don't make them undefined but rather point to \cs{@latex@info}
+% because that's what they replace. This way we can change
+% \cs{@latex@info} elsewhere without the need to further rollback
+% sections.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@latex@note}{Display notes}%
+%<latexrelease>
+%<latexrelease>\let\@latex@note\@latex@info
+%<latexrelease>\let\@latex@note@no@line\@latex@info@no@line
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+%
% \begin{macro}{\c@errorcontextlines}
% \changes{LaTeX2e}{1993/11/22}{Macro added}
% |\errorcontextlines| as a \LaTeX\ counter, so that it may be
@@ -591,10 +687,19 @@ Type H <return> for immediate help.}%
% RmS 1992/08/24: added code to |\@badend| to display position of
% non-matching |\begin|.
% FMi 1993/01/14: missing space added.
+%
+% The environment name has to literally match, i.e., what is stored
+% in \cs{@currenvir} (after one expansion) must match what is
+% passed to \cs{end} (without expansion). If not we complain. Not
+% the absolute best solution but at least it avoids getting
+% \verb=\begin{foo} ended by \end{foo}= which was possible in the
+% past.
+% \changes{v1.2t}{2021/08/20}{Improve \cs{@badend} error message (gh/587)}
% \begin{macrocode}
\gdef\@badend#1{%
- \@latex@error{\protect\begin{\@currenvir}\@currenvline
- \space ended by \protect\end{#1}}\@eha}
+ \@latex@error{\protect\begin
+ {\detokenize\expandafter{\@currenvir}}\@currenvline
+ \space ended by \protect\end{\detokenize{#1}}}\@eha}
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/ltexpl.dtx b/Master/texmf-dist/source/latex/base/ltexpl.dtx
index 6d7ec3ff60b..021edc644c3 100644
--- a/Master/texmf-dist/source/latex/base/ltexpl.dtx
+++ b/Master/texmf-dist/source/latex/base/ltexpl.dtx
@@ -86,7 +86,7 @@
% \end{macrocode}
% We only initialize these kernel hooks if they are not already
% existing. Otherwise they would be set to \cs{@empty} on rollback
-% which would be wrong because code that has been added to to them
+% which would be wrong because code that has been added to them
% may still have to be executed in the rollback situation . Instead
% code that writes to them needs to handle the rollback as needed.
% It is likely that we have to change that approach in the future,
diff --git a/Master/texmf-dist/source/latex/base/ltfilehook.dtx b/Master/texmf-dist/source/latex/base/ltfilehook.dtx
index 5d0acc8fdfb..000f4d8c2a2 100644
--- a/Master/texmf-dist/source/latex/base/ltfilehook.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfilehook.dtx
@@ -31,8 +31,8 @@
%%% From File: ltfilehook.dtx
%
% \begin{macrocode}
-\providecommand\ltfilehookversion{v1.0k}
-\providecommand\ltfilehookdate{2021/05/25}
+\providecommand\ltfilehookversion{v1.0l}
+\providecommand\ltfilehookdate{2021/08/27}
% \end{macrocode}
%
%<*driver>
@@ -48,7 +48,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
@@ -115,12 +115,12 @@
% \cs{usepackage}, etc. They are not called for files read using
% internal low-level methods, such as \cs{@input} or \cs{openin}.
%
-% \begin{variable}{file/before,file/before/...,
-% file/after/...,file/after,
+% \begin{variable}{file/before,file/.../before,
+% file/.../after,file/after,
% }
% These are:
% \begin{description}
-% \item[\texttt{file/before}, \texttt{file/before/\meta{file-name}}]
+% \item[\texttt{file/before}, \texttt{file/\meta{file-name}/before}]
%
% These hooks are executed in that order just before the file is
% loaded for reading. The code of the first hook is used
@@ -128,7 +128,7 @@
% file with matching \meta{file-name} allowing you to specify
% code that only applies to one file.
%
-% \item[\texttt{file/after/\meta{file-name}}, \texttt{file/after}]
+% \item[\texttt{file/\meta{file-name}/after}, \texttt{file/after}]
%
% These hooks are after the file with name \meta{file-name} has
% been fully consumed. The order is swapped (the specific one
@@ -149,9 +149,9 @@
% \begin{tabbing}
% mm\=mm\=mm\=mm\=\kill
% \>\cs{UseHook}\marg{\hook{file/before}} \\
-% \>\cs{UseHook}\marg{\hook{file/before/\meta{file name}}} \\
+% \>\cs{UseHook}\marg{\hook{file/\meta{file name}/before}} \\
% \>\> \meta{file contents} \\
-% \>\cs{UseHook}\marg{\hook{file/after/\meta{file name}}} \\
+% \>\cs{UseHook}\marg{\hook{file/\meta{file name}/after}} \\
% \>\cs{UseHook}\marg{\hook{file/after}}
% \end{tabbing}
%
@@ -172,8 +172,8 @@
%
% When a file is input, the \meta{file name} is available in
% \cs{CurrentFile}, which is then used when accessing the
-% \hook{file/before/\meta{file name}} and
-% \hook{file/after/\meta{file name}}.
+% \hook{file/\meta{file name}/before} and
+% \hook{file/\meta{file name}/after}.
%
% \begin{variable}{\CurrentFile}
% The name of the file about to be read (or just finished) is
@@ -216,7 +216,7 @@
% \cs{RequirePackage}, \cs{LoadPackageWithOptions}, etc.) offer the
% hooks from section~\ref{sec:general-file-hooks} when they are
% used to load a package or class file, e.g.,
-% \texttt{file/after/array.sty} would be called after the
+% \texttt{file/array.sty/after} would be called after the
% \pkg{array} package got loaded. But as packages and classes form as special group
% of files, there are some additional hooks available that only
% apply when a package or class is loaded.
@@ -224,9 +224,9 @@
%
% \begin{variable}{
% package/before,package/after,
-% package/before/...,package/after/...,
+% package/.../before,package/.../after,
% class/before,class/after,
-% class/before/...,class/after/...,
+% class/.../before,class/.../after,
% }
% These are:
% \begin{description}
@@ -234,8 +234,8 @@
%
% These hooks are called for each package being loaded.
%
-% \item[\texttt{package/before/\meta{name}},
-% \texttt{package/after/\meta{name}}]
+% \item[\texttt{package/\meta{name}/before},
+% \texttt{package/\meta{name}/after}]
%
% These hooks are additionally called if the package name is
% \meta{name} (without extension).
@@ -244,7 +244,7 @@
%
% These hooks are called for each class being loaded.
%
-% \item[\texttt{class/before/\meta{name}}, \texttt{class/after/\meta{name}}]
+% \item[\texttt{class/\meta{name}/before}, \texttt{class/\meta{name}/after}]
%
% These hooks are additionally called if the class name is
% \meta{name} (without extension).
@@ -258,16 +258,16 @@
% \begin{tabbing}
% mm\=mm\=mm\=mm\=\kill
% \>\cs{UseHook}\marg{\hook{package/before}} \\
-% \>\cs{UseHook}\marg{\hook{package/before/\meta{package name}}} \\[5pt]
+% \>\cs{UseHook}\marg{\hook{package/\meta{package name}/before}} \\[5pt]
% \>\>\cs{UseHook}\marg{\hook{file/before}} \\
-% \>\>\cs{UseHook}\marg{\hook{file/before/\meta{package name}.sty}} \\
+% \>\>\cs{UseHook}\marg{\hook{file/\meta{package name}.sty/before}} \\
% \>\>\> \meta{package contents} \\
-% \>\>\cs{UseHook}\marg{\hook{file/after/\meta{package name}.sty}} \\
+% \>\>\cs{UseHook}\marg{\hook{file/\meta{package name}.sty/after}} \\
% \>\>\cs{UseHook}\marg{\hook{file/after}} \\[5pt]
% \>\>\emph{code from \cs{AtEndOfPackage} if
% used inside the package} \\[5pt]
-% \>\cs{UseHook}\marg{\hook{package/after/\meta{package name}}} \\
-% \>\cs{UseHook}\marg{\hook{package/after}}
+% \>\cs{UseHook}\marg{\hook{package/\meta{package name}/after}} \\
+% \>\cs{UseHook}\marg{\hook{package/after}}
% \end{tabbing}
% and similar for class file loading, except that \texttt{package/}
% is replaced by \texttt{class/} and \cs{AtEndOfPackage} by
@@ -276,6 +276,20 @@
% If a package or class is not loaded (or it was loaded before the
% hooks were set) none of the hooks are executed!
%
+% All class or package hooks involving the name of the class or
+% package are implemented as
+% one-time hooks, whereas all other such hooks are normal hooks.
+% This allows for the following use case
+%\begin{verbatim}
+% \AddToHook{package/varioref/after}
+% { ... apply my customizations if the package gets
+% loaded (or was loaded already) ... }
+%\end{verbatim}
+% without the need to first test if the package is already loaded.
+%
+%
+%
+%
% \subsection{Hooks for \cs{include} files}
%
% To manage \cs{include} files, \LaTeX{} issues a \cs{clearpage}
@@ -300,14 +314,14 @@
% is \enquote{\texttt{No file \meta{filename}.tex}}).
%
%
-% \begin{variable}{include/before,include/before/...,
-% include/end,include/end/...,
-% include/after,include/after/...,
+% \begin{variable}{include/before,include/.../before,
+% include/end,include/.../end,
+% include/after,include/.../after,
% }
% These are:
% \begin{description}
%
-% \item[\texttt{include/before}, \texttt{include/before/\meta{name}}]
+% \item[\texttt{include/before}, \texttt{include/\meta{name}/before}]
%
% These hooks are executed (in that order) after the initial
% \cs{clearpage} and after \texttt{.aux} file is changed to use
@@ -317,14 +331,14 @@
% file.
%
%
-% \item[\texttt{include/end/\meta{name}}, \texttt{include/end}]
+% \item[\texttt{include/\meta{name}/end}, \texttt{include/end}]
%
% These hooks are executed (in that order) after \LaTeX{} has
% stopped reading from the \cs{include} file, but before it has
% issued a \cs{clearpage} to output any deferred floats.
%
%
-% \item[\texttt{include/after/\meta{name}}, \texttt{include/after}]
+% \item[\texttt{include/\meta{name}/after}, \texttt{include/after}]
%
% These hooks are executed (in that order) after \LaTeX{} has
% issued the \cs{clearpage} but before is has switched back
@@ -341,6 +355,13 @@
% normally does nothing, but starts a new page if further material
% got added this way.}
%
+%
+% All \hook{include} hooks involving the name of the included file are implemented as
+% one-time hooks (whereas all other such hooks are normal hooks).
+%
+%
+%
+%
% \subsection{High-level interfaces for \LaTeX{}}
%
% We do not provide any additional wrappers around the hooks (like
@@ -531,7 +552,7 @@
% The output of \cs{@@_file_parse_full_name:nN} is passed on to the
% |#2|---a 3-argument macro that takes the \meta{path}, \meta{base},
% and \meta{ext} parts of the file name.
-%
+%
% \begin{macrocode}
\cs_new:Npn \@@_file_parse_full_name:nN #1
{
@@ -591,6 +612,7 @@
% \changes{v1.0h}{2021/03/18}
% {Define \cs{g_@@_input_file_seq} to avoid losing data when
% rolling back.}
+% \changes{v1.0l}{2021/08/27}{Internal message name changes}
% \begin{macrocode}
\tl_new:N \l_@@_internal_tl
\seq_if_exist:NF \g_@@_input_file_seq
@@ -608,7 +630,7 @@
\seq_gpop:NNTF \g_@@_input_file_seq \l_@@_internal_tl
{ \exp_after:wN \@@_file_pop_assign:nnnn \l_@@_internal_tl }
{
- \msg_error:nnn { kernel } { should-not-happen }
+ \msg_error:nnn { latex2e } { should-not-happen }
{ Tried~to~pop~from~an~empty~file~name~stack. }
}
}
@@ -624,7 +646,7 @@
% \end{macro}
% \end{macro}
% \end{macro}
-%
+%
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
@@ -683,7 +705,7 @@
%<latexrelease> { \use_none:n #1 \prg_do_nothing: }
%<latexrelease> {#2}
%<latexrelease> }
-%<latexrelease>}
+%<latexrelease>}
%<latexrelease>\ExplSyntaxOff
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
@@ -697,16 +719,17 @@
%
% \subsection{Declaring the file-related hooks}
%
-% All hooks starting with \texttt{file/} \texttt{include/},
-% \texttt{class/} or \texttt{package/} are generic and will be
-% allocated if code is added to them. Thus there is no need to
-% explicitly declare any hook in the code below.
-%
-% Furthermore, those named \texttt{.../after} or \texttt{.../end} are
-% automatically declared as reversed hooks if filled with code, so this
-% is also automatically taken care of.
-%
+% These hooks have names with three-parts that
+% start with \hook{file/}, \hook{include/},
+% \hook{class/} or \hook{package/} and end with \hook{/before} or
+% \hook{/after} (or \hook{/end} in the case of \hook{include/}).
+% They are all generic hooks
+% so will be declared only if code is added to them;
+% this declaration is done for you automatically and, indeed, they should
+% not be declared explicitly.
%
+% Those named \hook{.../after} and \texttt{include/.../end}
+% are, when code is added, declared as reversed hooks.
%
%
% \subsection{Patching \LaTeX{}'s \cs{InputIfFileExists} command}
@@ -760,7 +783,7 @@
% can't rely on that still being true after the file has been
% processed. Thus for using the name in the file hooks we need to
% preserve the name and then restore it for the
-% \texttt{file/after/...} hook.
+% \texttt{file/.../after} hook.
%
% The hook always refers to the file requested by the user. The hook
% is \emph{always} loaded for \cs{CurrentFile} which usually is the
@@ -814,20 +837,27 @@
% The current file name is available in \cs{CurrentFile} so we use
% that in the specific hook.
% \begin{macrocode}
- \UseHook{file/before/\CurrentFile}%
+ \UseHook{file/\CurrentFile/before}%
\@@input #1% <- trailing space comes from \@filef@und
}%
% \end{macrocode}
% And here, \cs{CurrentFile} is restored
% (by \cs{@expl@@@filehook@file@pop@assign@@nnnn}) so we can use it once more.
% \begin{macrocode}
- \UseHook{file/after/\CurrentFile}%
+ \UseHook{file/\CurrentFile/after}%
\UseHook{file/after}}
\def\unqu@tefilef@und"#1" \@nil{#1}
+% \end{macrocode}
+%
+% \changes{v1.0l}{2021/08/25}{Declare non-generic file hooks}
+% Now declare the non-generic file hooks used above:
+% \begin{macrocode}
+\NewHook{file/before}
+\NewReversedHook{file/after}
%<latexrelease>\EndIncludeInRelease
%</2ekernel|latexrelease>
% \end{macrocode}
-%
+%
% \changes{v0.9b}
% {1993/12/04}{Macro added}
% \changes{v0.9p}
@@ -949,7 +979,7 @@
{ \if_meaning:w #1 #2 .tex \else: \token_to_str:N #2 \fi: }
% \end{macrocode}
% \end{macro}
-%
+%
% \begin{macro}[int]{\use_ii_iii:nnn}
% A variant of \cs[no-index]{use_...} to discard the first of three
% arguments.
@@ -1085,7 +1115,7 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
-%
+%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\set@curr@file}{Setting current file name}%
@@ -1108,7 +1138,7 @@
%<latexrelease> \endgroup}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
-%
+%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2019/10/01}%
%<latexrelease> {\set@curr@file}{Setting current file name}%
@@ -1124,7 +1154,7 @@
%<latexrelease>}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
-%
+%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\set@curr@file}{Setting current file name}%
@@ -1383,6 +1413,7 @@
% \@@_file_subst_cycle_error:NN,
% \@@_file_subst_cycle_error:cN,
% }
+% \changes{v1.0l}{2021/08/27}{Use \cs{msg_...} not \cs{__kernel_msg_...}}
% Showing this type of error expandably is tricky, as we have a very
% limited amount of characters to show and a potentially large list.
% As a work around, several errors are printed, each showing one step
@@ -1390,7 +1421,7 @@
% \begin{macrocode}
\cs_new:Npn \@@_file_subst_cycle_error:NN #1 #2
{
- \__kernel_msg_expandable_error:nnff { kernel } { file-cycle }
+ \msg_expandable_error:nnff { latex2e } { file-cycle }
{#1} { \use:c { @file-subst@ #1 } }
\token_if_eq_meaning:NNF #1 #2
{ \@@_file_subst_cycle_error:cN { @file-subst@ #1 } #2 }
@@ -1400,7 +1431,7 @@
%
% And the error message:
% \begin{macrocode}
-\__kernel_msg_new:nnn { kernel } { file-cycle }
+\msg_new:nnn { latex2e } { file-cycle }
{ File~loop!~#1~replaced~by~#2... }
% \end{macrocode}
% \end{macro}
@@ -1412,7 +1443,7 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
-%
+%
%
% \begin{macrocode}
%<@@=>
@@ -1438,7 +1469,7 @@
\def\disable@package@load#1#2{%
\global\@namedef{@pkg-disable@#1.\@pkgextension}{#2}}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\def\@disable@packageload@do#1#2{%
\@ifundefined{@pkg-disable@#1}{#2}%
@@ -1453,7 +1484,7 @@
\csname @pkg-disable@#1.\@pkgextension \endcsname \@undefined}
% \end{macrocode}
%
-%
+%
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
@@ -1502,7 +1533,7 @@
%<latexrelease> {\@expl@@@filehook@if@no@extension@@nTF}{2e tmp interfaces}%
\ExplSyntaxOn
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@if@no@extension@@nTF
\__filehook_if_no_extension:nTF
@@ -1512,7 +1543,7 @@
\cs_new_eq:NN \@expl@@@filehook@set@curr@file@@nNN
\__filehook_set_curr_file:nNN
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@resolve@file@subst@@w
\__filehook_resolve_file_subst:w
@@ -1522,7 +1553,7 @@
\cs_new_eq:NN \@expl@@@filehook@normalize@file@name@@w
\__filehook_normalize_file_name:w
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@if@file@replaced@@TF
\__filehook_if_file_replaced:TF
@@ -1537,23 +1568,23 @@
\cs_new_eq:NN \@expl@@@filehook@drop@extension@@N
\__filehook_drop_extension:N
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@file@push@@
\__filehook_file_push:
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@file@pop@@
\__filehook_file_pop:
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@file@pop@assign@@nnnn
\__filehook_file_pop_assign:nnnn
% \end{macrocode}
% \InternalDetectionOn
-%
+%
%
% \begin{macrocode}
\ExplSyntaxOff
@@ -1682,7 +1713,7 @@
%<*atveryend-ltx>
\ProvidesPackage{atveryend-ltx}
[2020/08/19 v1.0a
- Emulation of the original atvery package^^Jwith kernel methods]
+ Emulation of the original atveryend package^^Jwith kernel methods]
% \end{macrocode}
%
%
@@ -1698,14 +1729,14 @@
% \begin{macrocode}
\newcommand\AtEndAfterFileList{\AddToHook{enddocument/info}}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\newcommand\AtVeryVeryEnd {\AddToHook{enddocument/end}}
% \end{macrocode}
%
% \begin{macro}{\BeforeClearDocument}
% This one is the only one we don't implement or rather don't have
-% a dedicated hook in the code.
+% a dedicated hook in the code.
% \begin{macrocode}
\ExplSyntaxOn
\newcommand\BeforeClearDocument[1]
@@ -1713,7 +1744,7 @@
\atveryend@DEPRECATED{BeforeClearDocument \tl_to_str:n{#1}}
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new:Npn\atveryend@DEPRECATED #1
{\iow_term:x{======~DEPRECATED~USAGE~#1~==========}}
@@ -1721,7 +1752,7 @@
% \end{macrocode}
% \end{macro}
%
-%
+%
% \begin{macrocode}
%</atveryend-ltx>
% \end{macrocode}
@@ -1735,4 +1766,3 @@
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-
diff --git a/Master/texmf-dist/source/latex/base/ltfiles.dtx b/Master/texmf-dist/source/latex/base/ltfiles.dtx
index bcaac582208..4c24716df65 100644
--- a/Master/texmf-dist/source/latex/base/ltfiles.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfiles.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfiles.dtx}
- [2021/04/17 v1.2m LaTeX Kernel (File Handling)]
+ [2021/10/14 v1.2p LaTeX Kernel (File Handling)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfiles.dtx}
@@ -823,8 +823,16 @@
%
% \changes{v1.2j}{2020/10/04}{Quotes around the aux file name removed,
% they are not needed and upset BibTeX (gh/400)}
+% \changes{v1.2p}{2021/10/14}{Warn about use in preamble}
% \begin{macrocode}
\def\@include#1 {%
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ifx\@nodocument\relax
+% \end{macrocode}
+%
+% \begin{macrocode}
\clearpage
\if@filesw
\immediate\write\@mainaux{\string\@input{#1.aux}}%
@@ -850,16 +858,19 @@
% \end{macrocode}
% Execute the \texttt{before} hooks just after we switched the
% \texttt{.aux} file \ldots
+% \changes{v1.2n}{2021/07/23}{Make include/name/before a one-time hook}
+% \changes{v1.2o}{2021/08/25}{Standardise generic hook names (gh/648)}
% \begin{macrocode}
\UseHook{include/before}%
- \UseHook{include/before/#1}%
+ \UseOneTimeHook{include/#1/before}%
%-----------------------------------------
\@input@{#1.tex}%
%-----------------------------------------
% \end{macrocode}
% \ldots{} then \texttt{end} hooks \ldots
+% \changes{v1.2n}{2021/07/23}{Make include/name/end a one-time hook}
% \begin{macrocode}
- \UseHook{include/end/#1}%
+ \UseOneTimeHook{include/#1/end}%
\UseHook{include/end}%
%-----------------------------------------
\clearpage
@@ -869,8 +880,9 @@
% followed by another \cs{clearpage} just in case new material got
% added (after all we need to be in well defined state after the
% \cs{include}).
+% \changes{v1.2n}{2021/07/23}{Make include/name/after a one-time hook}
% \begin{macrocode}
- \UseHook{include/after/#1}%
+ \UseOneTimeHook{include/#1/after}%
\UseHook{include/after}%
\clearpage
%-----------------------------------------
@@ -888,7 +900,23 @@
\deadcycles\z@
\@nameuse{cp@#1}%
\fi
- \let\@auxout\@mainaux}
+ \let\@auxout\@mainaux
+% \end{macrocode}
+%
+% \begin{macrocode}
+\else
+\@latex@warning{%
+ \noexpand\include should only be used after \string\begin{document}}%
+\@input@{#1}%
+\fi}
+% \end{macrocode}
+%
+% \changes{v1.2o}{2021/08/25}{Declare non-generic include hooks}
+% Now declare the non-generic \hook{include} hooks used above:
+% \begin{macrocode}
+\NewHook{include/before}
+\NewReversedHook{include/end}
+\NewReversedHook{include/after}
%<latexrelease>\EndIncludeInRelease
%</2ekernel|latexrelease>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltfinal.dtx b/Master/texmf-dist/source/latex/base/ltfinal.dtx
index 19f82934aa6..40017a205a4 100644
--- a/Master/texmf-dist/source/latex/base/ltfinal.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfinal.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfinal.dtx}
- [2021/04/18 v2.2o LaTeX Kernel (Final Settings)]
+ [2021/09/06 v2.2q LaTeX Kernel (Final Settings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfinal.dtx}
@@ -1074,9 +1074,11 @@
}}
% \end{macrocode}
%
+% \changes{v2.2q}{2021/09/06}{Correctly upper and lowercase
+% \cs{ij} and \cs{IJ} (gh/658)}
% \begin{macrocode}
\def\@uclclist{\oe\OE\o\O\ae\AE
- \dh\DH\dj\DJ\l\L\ng\NG\ss\SS\th\TH}
+ \dh\DH\dj\DJ\l\L\ng\NG\ss\SS\ij\IJ\th\TH}
% \end{macrocode}
% The above code works, but has the nasty side-effect that if you
% say something like:
@@ -1244,6 +1246,39 @@
% \end{macro}
% \end{macro}
%
+% \subsection{Preparation for supporting PDF in backends}
+%
+% At the current point in time, basic support for PDF in
+% backends is not part of \LaTeX{} core; it is provided by external
+% packages. At some time in the future that work will be placed
+% into the kernel but for now it is separate and has to be
+% explicitly loaded in the document.
+%
+% In that code there is a command \cs{IfPDFManagementActiveTF}
+% which can be used by packages in order to execute different
+% code depending on the whether this basic backend support is loaded.
+%
+% To make this also work properly when this external package is not
+% loaded at all, we here add this command already in the
+% kernel (with a trivial definition); thus any package can
+% query this loading state in all circumstances.
+% Once this basic PDF backend
+% support gets moved to the kernel, this definition will vanish
+% again from here or, rather, it will be replaced by a real test.
+%
+% \begin{macro}{\IfPDFManagementActiveTF}
+% So long as the code for the basic backend support for PDF is not
+% loaded, the test that is implicit here will
+% always return the false branch.
+% Once this code is loaded, this definition will get
+% replaced by a real test (as it is then possible that the
+% management code is either activated or not activated).
+% \changes{v2.2p}{2021/08/08}{Default definition added (gh/640)}
+% \begin{macrocode}
+\let \IfPDFManagementActiveTF \@secondoftwo
+% \end{macrocode}
+% \end{macro}
+%
%
%
% \subsection{Do some temporary work for pre-release}
@@ -1253,7 +1288,7 @@
% \begin{macrocode}
% \end{macrocode}
%
-% \subsection{Some last minute initializations \ldots}
+% \subsection{Some last minute initializations \ldots}
%
% Load the first aid set of definitions for external packages that await updates.
% \changes{v2.2j}{2020/09/26}
diff --git a/Master/texmf-dist/source/latex/base/ltfloat.dtx b/Master/texmf-dist/source/latex/base/ltfloat.dtx
index ed25db3ed10..ac3b6418171 100644
--- a/Master/texmf-dist/source/latex/base/ltfloat.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfloat.dtx
@@ -31,7 +31,7 @@
%
%<*driver>
% \fi
-\ProvidesFile{ltfloat.dtx}[2021/03/03 v1.2f LaTeX Kernel (Floats)]
+\ProvidesFile{ltfloat.dtx}[2021/10/14 v1.2g LaTeX Kernel (Floats)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfloat.dtx}
@@ -1510,10 +1510,12 @@
% {Missing percent, again}
% \changes{v1.2e}{2021/02/10}{Explicitly run \cs{par} at the end of footnote text
% in preparation for paragraph hooks}
+% \changes{v1.2g}{2021/10/14}
+% {Explicitly set \cs{@currentcounter} (gh/687)}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease>\IncludeInRelease{2021/11/15}%
%<latexrelease> {\@footnotetext}{footnotetext tagging}%
\long\def\@footnotetext#1{\insert\footins{%
\reset@font\footnotesize
@@ -1521,6 +1523,7 @@
\splittopskip\footnotesep
\splitmaxdepth \dp\strutbox \floatingpenalty \@MM
\hsize\columnwidth \@parboxrestore
+ \def\@currentcounter{footnote}%
\protected@edef\@currentlabel{%
\csname p@footnote\endcsname\@thefnmark
}%
@@ -1534,6 +1537,26 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@footnotetext}{footnotetext tagging}%
+%<latexrelease>\long\def\@footnotetext#1{\insert\footins{%
+%<latexrelease> \reset@font\footnotesize
+%<latexrelease> \interlinepenalty\interfootnotelinepenalty
+%<latexrelease> \splittopskip\footnotesep
+%<latexrelease> \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
+%<latexrelease> \hsize\columnwidth \@parboxrestore
+%<latexrelease> \protected@edef\@currentlabel{%
+%<latexrelease> \csname p@footnote\endcsname\@thefnmark
+%<latexrelease> }%
+%<latexrelease> \color@begingroup
+%<latexrelease> \@makefntext{%
+%<latexrelease> \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+%<latexrelease> \par
+%<latexrelease> \color@endgroup}}%
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\@footnotetext}{footnotetext tagging}%
%<latexrelease>
diff --git a/Master/texmf-dist/source/latex/base/ltfntcmd.dtx b/Master/texmf-dist/source/latex/base/ltfntcmd.dtx
index 5f70053a688..6c4ec4b3d16 100644
--- a/Master/texmf-dist/source/latex/base/ltfntcmd.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfntcmd.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfntcmd.dtx}
- [2020/12/05 v3.4c LaTeX Kernel (Font commands)]
+ [2021/09/12 v3.5a LaTeX Kernel (Font commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfntcmd.dtx}
@@ -466,9 +466,10 @@
% Is this the correct action in the `empty' case? It is efficient but
% typographically it is, strictly, incorrect!
% \changes{v3.3l}{1994/06/18}{Added check for empty text}
+% \changes{v3.5a}{2021/09/12}{use \cs{unexpanded} to make \# safe}
% \begin{macrocode}
\def \text@command #1{%
- \def \reserved@a {#1}%
+ \edef \reserved@a {\unexpanded{#1}}%
\ifx \reserved@a \@empty
\let \check@icl \@empty
\let \check@icr \@empty
diff --git a/Master/texmf-dist/source/latex/base/ltfssbas.dtx b/Master/texmf-dist/source/latex/base/ltfssbas.dtx
index df265d0b0fc..1f30372d063 100644
--- a/Master/texmf-dist/source/latex/base/ltfssbas.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssbas.dtx
@@ -35,7 +35,7 @@
%
%
\ProvidesFile{ltfssbas.dtx}
- [2021/04/26 v3.2i LaTeX Kernel (NFSS Basic Macros)]
+ [2021/06/09 v3.2j LaTeX Kernel (NFSS Basic Macros)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -280,11 +280,12 @@
% may have dropped an ``m''. If nothing has changes,
% fine. Otherwise there was a wrong value which is now corrected in
% \cs{reservedb} so we use that and also issue a warning.
+% \changes{v3.2j}{2021/06/09}{Improve information message}
% \begin{macrocode}
\edef\reserved@a{#3}%
\series@maybe@drop@one@m\reserved@a\reserved@b
\ifx\reserved@a\reserved@b\else
- \@latex@warning{Font shape declaration has incorrect series
+ \@latex@note{Font shape #1/#2/#3/#4 has incorrect series
value `#3'.\MessageBreak It should not contain an `m'!
Please correct it.\MessageBreak Found}%
\fi
diff --git a/Master/texmf-dist/source/latex/base/ltfssdcl.dtx b/Master/texmf-dist/source/latex/base/ltfssdcl.dtx
index 9710d543829..4f2cabd613b 100644
--- a/Master/texmf-dist/source/latex/base/ltfssdcl.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssdcl.dtx
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssdcl.dtx}
- [2021/02/15 v3.0w LaTeX Kernel (NFSS Declarative Interface)]
+ [2021/10/15 v3.0y LaTeX Kernel (NFSS Declarative Interface)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -454,25 +454,88 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
+% \begin{macro}{\c@localalphabets}
+% \changes{v3.0x}{2021/09/26}{Counter added for (gh/676)}
+% To avoid hitting the ``no more math fams available'' limit of 16, we
+% keep a defined number of math alphabets flexible/local. If we have to
+% allocate any of those we roll back the allocation after the
+% formula has ended, so the next formula can use other alphabets in
+% the slot(s). This makes the processing a bit slower if you are
+% working at the limit, but that is better than dying with ``out of memory''.
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2021/11/15}
+%<latexrelease> {\document@select@group}{\document@select@group}%
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+% We don't really undo the declaration on rollback (as that would
+% be hard to maintain), so rolling
+% forward needs to check if the declaration was already made.
+% \begin{macrocode}
+\ifx\c@localmathalphabets\@undefined
+% \end{macrocode}
+% There is no need to have this counter as part of the include
+% checkpoints, given that it makes little sense to alter its
+% settings mid document. All we want is the ability to change it
+% using the \cs{setcounter} interface.
+%
+% By default we keep two math fams flexible.
+% \begin{macrocode}
+ \newcount\c@localmathalphabets
+ \setcounter{localmathalphabets}{2}
+\fi
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
% \begin{macro}{\document@select@group}
-% We surround |\select@group| with braces so that functions using it
-% can be used directly after |_| or |^|.
-% \changes{v2.1p}{1994/12/10}{Surround with braces (add fourth arg)}
-% \changes{v2.1q}{1995/04/02}{fix problem for pr/1275}
+% The \cs{document@select@group} command is the version of
+% \cs{select@group} (inside math versions) that is used in the
+% document body to set up math alphabets (if used).
+%
% \changes{v3.0g}{1997/11/20}
% {(DPC) inline use of \cs{stepcounter} (faster, and saves a csname
% per math version as no reset list)}
% \changes{v3.0q}{2015/03/18}{Introduce \cs{e@mathgroup@top}}
% \begin{macrocode}
-%</2ekernel>
-%<latexrelease>\IncludeInRelease{2020/10/01}
-%<latexrelease> {\document@select@group}{\document@select@group}%
-%<*2ekernel|latexrelease>
\def\document@select@group#1#2#3#4{%
\ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi
{%
\ifmmode
+% \end{macrocode}
+% We first check if there is still room for allocating another
+% mathgroup. If there is, we check if it can be globally allocated
+% or if we have reached the limit which is given by
+% \cs{e@mathgroup@top} with \cs{c@localmathalphabets} subtracted.
+%
+% \changes{v3.0x}{2021/09/26}{Test if we should freeze the version (gh/676)}
+% \begin{macrocode}
\ifnum\csname c@mv@\math@version\endcsname<\e@mathgroup@top
+ \ifnum \numexpr\e@mathgroup@top-\c@localmathalphabets
+ >\csname c@mv@\math@version\endcsname
+ \else
+% \end{macrocode}
+% If we are past this point we freeze the current state of the math
+% version so that we can return to it after the formula has
+% ended. Of course, that should be done only once, so we check if
+% \cs{mv@\meta{version}@frozen} already exists.
+% \begin{macrocode}
+ \ifcsname mv@\math@version @frozen\endcsname \else
+% \end{macrocode}
+% We have to pass the current value of \cs{math@version} not the
+% macro itself, because some of the processing is delayed to a
+% point where the value may have changed again---not doing this
+% caused a puzzling error in one setup.
+% \begin{macrocode}
+ \expandafter\freeze@math@version\expandafter{\math@version}%
+ \fi
+ \fi
\begingroup
\escapechar\m@ne
\getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3%
@@ -486,16 +549,21 @@
\global\advance\csname c@mv@\math@version\endcsname\@ne
\else
\let#1\relax
- \@latex@error{Too many math alphabets used
- in version \math@version}%
+ \@latex@error{Too many math alphabets used in
+ version \math@version}%
\@eha
\fi
% \end{macrocode}
-% extra \cs{expandafter} to remove the \cs{expandafter} added below
-% \changes{v3.0w}{2021/02/115}{fix for (gh/501)}
+% Extra \cs{expandafter} to remove the \cs{expandafter} added below
+% \changes{v3.0w}{2021/02/15}{fix for (gh/501)}
% \begin{macrocode}
\else \expandafter\expandafter\expandafter\non@alpherr\fi
% \end{macrocode}
+% We surround |\select@group| with braces so that functions using it
+% can be used directly after |_| or |^|.
+% \changes{v2.1p}{1994/12/10}{Surround with braces (add fourth arg)}
+% \changes{v2.1q}{1995/04/02}{fix problem for pr/1275}
+%
% If the legacy interface is used, e.g., \verb=$\sf -1$= the math
% alphabet \verb=#1= does not take an argument so we better do not
% surround \verb=#4= with braces, because then we get
@@ -507,8 +575,142 @@
\expandafter#1\ifx\math@bgroup\bgroup{#4}\else#4\fi
}%
}
+% \end{macrocode}
+%
+%
+%
+% \begin{macro}{\freeze@math@version}
+% \changes{v3.0x}{2021/09/26}{Macro added for (gh/676)}
+% This command stores the current state of the math version and sets
+% things up to return to it after each formula from now on. We use
+% L3 programming layer code to set it up.
+% \begin{macrocode}
+\ExplSyntaxOn
+\cs_new_protected:Npn\freeze@math@version #1 {
+% \end{macrocode}
+% Save the current \cs{mv@\meta{version}} code and the number of
+% allocated mathgroups inside.
+% \begin{macrocode}
+ \@font@info{Freeze~ math~ alphabet~ allocation~ in~ version~
+ #1.\MessageBreak
+ Allocated~math~groups:~\int_use:c{ c@mv@ #1 }~
+ (local:~ \int_use:N\c@localmathalphabets) }
+ \cs_gset_eq:cc { mv@#1@frozen }{ mv@#1 }
+ \tl_gset:cx { g__nfss_frozen_mv_ #1 _tl }{ \int_use:c { c@mv@#1 } }
+% \end{macrocode}
+% Doing the reset the first time, we wait until we are out of
+% math mode, so we use some recursive \cs{group_insert_after:N} for this
+% before we execute \cs{mv@\meta{version}@reset}.
+% \begin{macrocode}
+ \group_insert_after:N \__nfss_init_mv_freeze:N \exp_after:wN
+ \group_insert_after:N \cs:w mv@#1@reset \cs_end:
+% \end{macrocode}
+% The \cs{check@mathfonts} is called at the very beginning of each
+% math formula, so it is a good way to hook in the resetting.
+% Again that has to happen after the formula has ended, but we know
+% because of the place where \cs{check@mathfonts} is used
+% that a single \cs{aftergoup} is sufficient.
+% \begin{macrocode}
+ \tl_gput_right:No \check@mathfonts
+ {
+ \exp_after:wN \group_insert_after:N \cs:w mv@#1@reset \cs_end:
+ }
+% \end{macrocode}
+% Here is the definition of \cs{mv@\meta{version}@reset}. If there
+% has been no new math alphabet allocation, doing a reset would
+% just cause a lot of unnecessary processing, so we do a quick
+% check upfront for this.
+% \begin{macrocode}
+ \cs_gset:cpn{mv@#1@reset}
+ {
+ \int_compare:nNnTF { \int_use:c{c@mv@#1} } >
+ { \tl_use:c{g__nfss_frozen_mv_ #1 _tl} }
+ {
+ \@font@info{Undo~ math~ alphabet~ allocation~ in~ version~ #1}
+% \end{macrocode}
+% If the undo is necessary, we restore the \cs{mv@\meta{version}} code.
+% \begin{macrocode}
+ \cs_gset_eq:cc { mv@#1 }{ mv@#1@frozen }
+ \int_gset:cn { c@mv@#1 }{ \tl_use:c {g__nfss_frozen_mv_ #1 _tl} }
+% \end{macrocode}
+% But we also should undo changes to the math alphabet
+% definitions. We therefore run this code with a modified
+% definition for \cs{getanddefine@fonts} because there is no need
+% to do anything to the symbol fonts that are permanently allocated.
+% \begin{macrocode}
+ \group_begin:
+ \cs_set_eq:NN \getanddefine@fonts \use_none:nn
+ \use:c {mv@#1}
+ \group_end:
+ }
+ {
+% \end{macrocode}
+% If there was no change, we report that in the log (but this
+% branch could go completely).
+% \begin{macrocode}
+ \@font@info{No~ math~ alphabet~ change~ to~ frozen~ version~ #1}
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\__nfss_init_mv_freeze:N}
+% \changes{v3.0x}{2021/09/26}{Macro added for (gh/676)}
+% To do the initial freeze in a safe place, we check if we are in
+% math mode and if so try again after the group has ended by pushing
+% the command and its single token argument with two
+% \cs{group_insert_after:N}s after the current group. If we are no longer in
+% math mode we bypass the
+% conditional and so the next token is our argument
+% which is then finally executed.
+% \begin{macrocode}
+\cs_new_protected:Npn \__nfss_init_mv_freeze:N #1 {%
+ \mode_if_math:T { \group_insert_after:N \__nfss_init_mv_freeze:N
+ \group_insert_after:N } #1
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\document@select@group}{\document@select@group}%
+%<latexrelease>
+%<latexrelease>\def\document@select@group#1#2#3#4{%
+%<latexrelease> \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi
+%<latexrelease> {%
+%<latexrelease> \ifmmode
+%<latexrelease> \ifnum\csname c@mv@\math@version\endcsname<\e@mathgroup@top
+%<latexrelease> \begingroup
+%<latexrelease> \escapechar\m@ne
+%<latexrelease> \getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3%
+%<latexrelease> \globaldefs\@ne \math@fonts
+%<latexrelease> \endgroup
+%<latexrelease> \expandafter\extract@alph@from@version
+%<latexrelease> \csname mv@\math@version\expandafter\endcsname
+%<latexrelease> \expandafter{\number\csname
+%<latexrelease> c@mv@\math@version\endcsname}%
+%<latexrelease> #1%
+%<latexrelease> \global\advance\csname c@mv@\math@version\endcsname\@ne
+%<latexrelease> \else
+%<latexrelease> \let#1\relax
+%<latexrelease> \@latex@error{Too many math alphabets used
+%<latexrelease> in version \math@version}%
+%<latexrelease> \@eha
+%<latexrelease> \fi
+%<latexrelease> \else \expandafter\expandafter\expandafter\non@alpherr\fi
+%<latexrelease> \expandafter#1\ifx\math@bgroup\bgroup{#4}\else#4\fi
+%<latexrelease> }%
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2015/01/01}
%<latexrelease> {\document@select@group}{\document@select@group}%
%<latexrelease>
@@ -653,9 +855,36 @@
%
% \begin{macro}{\DeclareMathVersion}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\DeclareMathVersion}{local alphabets}%
\def\DeclareMathVersion#1{%
+% \end{macrocode}
+% When declaring a new math version we need to instantiate an L3
+% variable that is used when we freeze the version, because too many
+% alphabets got allocated. If we don't do this, L3 programming layer
+% complains if it is run in checking mode.
+% \changes{v3.0y}{2021/10/15}{Initialize variable for freezing
+% math version (gh/676)}
+% \begin{macrocode}
+ \@namedef{g__nfss_frozen_mv_#1_tl}{}%
+% \end{macrocode}
+%
+% \begin{macrocode}
\expandafter\new@mathversion\csname mv@#1\endcsname}
\@onlypreamble\DeclareMathVersion
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\DeclareMathVersion}{local alphabets}%
+%<latexrelease>\def\DeclareMathVersion#1{%
+%<latexrelease> \expandafter\new@mathversion\csname mv@#1\endcsname}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/ltfssini.dtx b/Master/texmf-dist/source/latex/base/ltfssini.dtx
index b06fc161b08..f817fdd8473 100644
--- a/Master/texmf-dist/source/latex/base/ltfssini.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssini.dtx
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssini.dtx}
- [2021/04/26 v3.2h LaTeX Kernel (NFSS Initialisation)]
+ [2021/09/10 v3.2i LaTeX Kernel (NFSS Initialisation)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -207,7 +207,7 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease>\IncludeInRelease{2021/11/15}%
%<latexrelease> {\DeclareFontSeriesDefault}{Custom series}%
% \end{macrocode}
%
@@ -280,6 +280,17 @@
% \begin{macrocode}
\let\DeclareFontSeriesDefault\@undefined % for rollback
\newcommand\DeclareFontSeriesDefault[3][]{%
+% \end{macrocode}
+%
+% \changes{v3.2i}{2021/09/10}{Do delayed changes to \cs{bfdefault} or
+% \cs{mddefault} first (gh/663)}
+% \begin{macrocode}
+ \expand@font@defaults
+ \maybe@update@bfseries@defaults
+ \maybe@update@mdseries@defaults
+% \end{macrocode}
+%
+% \begin{macrocode}
\def\reserved@a{#1}%
% \end{macrocode}
% No optional argument: set up general default.
@@ -333,7 +344,77 @@
% \end{macro}
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\DeclareFontSeriesDefault}{Custom series}%
+%<latexrelease>
+%<latexrelease>\let\DeclareFontSeriesDefault\@undefined % for rollback
+%<latexrelease>\newcommand\DeclareFontSeriesDefault[3][]{%
+%<latexrelease> \def\reserved@a{#1}%
+%<latexrelease> \ifx\reserved@a\@empty
+%<latexrelease> \ifcsname #2series\endcsname % supported are
+%<latexrelease> % \[md/bf]default
+%<latexrelease> \expandafter\def
+%<latexrelease> \csname #2default\endcsname{#3\@empty}%
+%<latexrelease> \expandafter\def
+%<latexrelease> \csname #2default@previous\endcsname{#3\@empty}%
+%<latexrelease> \else
+%<latexrelease> \@latex@error{Wrong syntax for \string\DeclareFontSeriesDefault}%
+%<latexrelease> {Mandatory first argument must be 'md' or 'bf'.}
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \ifcsname #2series@#1\endcsname % supported are
+%<latexrelease> % \[md/bf]series@[rm/sf/tt]
+%<latexrelease> \expandafter\edef
+%<latexrelease> \csname #2series@#1\endcsname{#3}%
+%<latexrelease> \expandafter\let
+%<latexrelease> \csname #2series@#1@kernel\endcsname\@undefined
+%<latexrelease> \else
+%<latexrelease> \@latex@error{Wrong syntax for \string\DeclareFontSeriesDefault}%
+%<latexrelease> {Optional argument must be 'rm', 'sf', or 'tt'. \MessageBreak
+%<latexrelease> Mandatory first argument must be 'md' or 'bf'.}
+%<latexrelease> \fi
+%<latexrelease> \fi
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\DeclareFontSeriesDefault}{Custom series}%
+%<latexrelease>
+%<latexrelease>\let\DeclareFontSeriesDefault\@undefined
+%<latexrelease>\let\bfseries@rm\@undefined
+%<latexrelease>\let\bfseries@sf\@undefined
+%<latexrelease>\let\bfseries@tt\@undefined
+%<latexrelease>\let\bfseries@rm@kernel\@undefined
+%<latexrelease>\let\bfseries@sf@kernel\@undefined
+%<latexrelease>\let\bfseries@tt@kernel\@undefined
+%<latexrelease>\let\mdseries@rm\@undefined
+%<latexrelease>\let\mdseries@sf\@undefined
+%<latexrelease>\let\mdseries@tt\@undefined
+%<latexrelease>\expandafter\let\csname ver@mweights.sty\endcsname\@undefined
+%<latexrelease>
+%<latexrelease>\let\@meta@family@list\@undefined
+%<latexrelease>\let\prepare@family@series@update\@undefined
+%<latexrelease>\let\update@series@target@value\@undefined
+%<latexrelease>
+% \end{macrocode}
+% This is always called in \cs{document} so don't make it undefined.
+% \begin{macrocode}
+%<latexrelease>\let\init@series@setup\relax
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\mdseries@rm}{Custom series}%
+% \end{macrocode}
% \begin{macro}{\mdseries@rm}
% \begin{macro}{\mdseries@sf}
@@ -704,9 +785,8 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\DeclareFontSeriesDefault}{Custom series}%
+%<latexrelease> {\mdseries@rm}{Custom series}%
%<latexrelease>
-%<latexrelease>\let\DeclareFontSeriesDefault\@undefined
%<latexrelease>\let\bfseries@rm\@undefined
%<latexrelease>\let\bfseries@sf\@undefined
%<latexrelease>\let\bfseries@tt\@undefined
@@ -735,55 +815,11 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease>\IncludeInRelease{2021/11/15}%
%<latexrelease> {\bfseries}{Custom series with hooks}%
% \end{macrocode}
-% \begin{macro}{\expand@font@defaults}
-% \begin{macro}{\rm@def@ult}
-% \begin{macro}{\sf@def@ult}
-% \begin{macro}{\tt@def@ult}
-% \begin{macro}{\md@def@ult}
-% \begin{macro}{\bf@def@ult}
-%
-% The family specific defaults are fully expanded, i.e., they are
-% defined via \cs{edef} inside \cs{DeclareFontSeriesDefault}.
-% However, the overall defaults, e.g., \cs{bfdefault} may have been
-% redefined by the user and thus may not be fully expanded. So to
-% enable reliable comparison we make expanded versions of
-% them. That we rerun each time. The alternative would be to only
-% allow for changes before begin document.
-% \begin{macrocode}
-\def\expand@font@defaults{%
- \edef\rmdef@ult{\rmdefault}%
- \edef\sfdef@ult{\sfdefault}%
- \edef\ttdef@ult{\ttdefault}%
-% \end{macrocode}
-% The series defaults may contain some surplus \texttt{m} that we
-% need to drop here.
-% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{bfdef@ult}
-% and \cs{mddef@ult} (gh/291)}
-% \begin{macrocode}
- \series@maybe@drop@one@m\bfdefault\bfdef@ult
- \series@maybe@drop@one@m\mddefault\mddef@ult
-% \end{macrocode}
-% Formats that set up parallel fonts, e.g., for Japanese, can use
-% this hook to add additional code here.
-% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)}
-% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
-% \begin{macrocode}
- \UseHook{expand@font@defaults}%
-}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-
-
% \begin{macro}{\bfseries}
% This document command switches to the bold series.
% \begin{macrocode}
@@ -797,9 +833,35 @@
% \cs{ttdef@ult} and the select the correct family default in that case.
% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside
% of \cs{fontseries} argument so that it is not done several times}
+% \changes{v3.2i}{2021/09/10}{Do delayed changes to \cs{bfdefault} in
+% a separate macro for better reuse (gh/663)}
% \begin{macrocode}
\expand@font@defaults
+ \maybe@update@bfseries@defaults
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
+ \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
+ \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
+% \end{macrocode}
+% If not \cs{bfdefault} is used.
+% \begin{macrocode}
+ \else \fontseries\bfdefault
+ \fi\fi\fi
% \end{macrocode}
+% This hook in contrast is always executed.
+% \begin{macrocode}
+ \UseHook{bfseries}%
+ \selectfont
+}
+% \end{macrocode}
+% \end{macro}
+
+
+
+% \begin{macro}{\maybe@update@bfseries@defaults}
+%
% If \cs{bfdefault} and \cs{bfdefault@previous} are different then
% the default got changed directly through the legacy interface
% (i.e., via \cs{def} or \cs{renewcommand}. In that case we reset
@@ -807,7 +869,10 @@
% the case before the new mechanism was introduced.
% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault}
% and \cs{mddefault} (gh/306)}
+% \changes{v3.2i}{2021/09/10}{Do delayed changes to \cs{bfdefault} in
+% a separate macro for better reuse (gh/663)}
% \begin{macrocode}
+\def\maybe@update@bfseries@defaults{%
\ifx\bfdefault\bfdefault@previous\else
% \end{macrocode}
% We add \cs{@empty} and then let \cs{bfdefault@previous} to
@@ -835,28 +900,11 @@
% \begin{macrocode}
\UseHook{bfseries/defaults}%
\fi
-% \end{macrocode}
-%
-% \begin{macrocode}
- \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
- \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
- \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
-% \end{macrocode}
-% If not \cs{bfdefault} is used.
-% \begin{macrocode}
- \else \fontseries\bfdefault
- \fi\fi\fi
-% \end{macrocode}
-% This hook in contrast is always executed.
-% \begin{macrocode}
- \UseHook{bfseries}%
- \selectfont
}
% \end{macrocode}
% \end{macro}
-
% \begin{macro}{\mdseries}
% This document command switches to the medium series.
% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside
@@ -865,10 +913,30 @@
% and \cs{mddefault} (gh/306)}
% \changes{v3.2d}{2020/09/30}{\cs{mddefault@previous} not \cs{mdseries@previous}
% (gh/395)}
+% \changes{v3.2i}{2021/09/10}{Do delayed changes to \cs{mddefault} in
+% a separate macro for better reuse (gh/663)}
% \begin{macrocode}
\DeclareRobustCommand\mdseries{%
\not@math@alphabet\mdseries\relax
\expand@font@defaults
+ \maybe@update@mdseries@defaults
+ \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
+ \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
+ \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
+ \else \fontseries\mddefault
+ \fi\fi\fi
+ \UseHook{mdseries}%
+ \selectfont
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\maybe@update@mdseries@defaults}
+%
+% \changes{v3.2i}{2021/09/10}{Do delayed changes to \cs{mddefault} in
+% a separate macro for better reuse (gh/663)}
+% \begin{macrocode}
+\def\maybe@update@mdseries@defaults{%
\ifx\mddefault\mddefault@previous\else
\expandafter\def\expandafter\mddefault\expandafter{\mddefault\@empty}%
\let\mddefault@previous\mddefault
@@ -884,17 +952,161 @@
% \begin{macrocode}
\UseHook{mdseries/defaults}%
\fi
- \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
- \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
- \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
- \else \fontseries\mddefault
- \fi\fi\fi
- \UseHook{mdseries}%
- \selectfont
}
% \end{macrocode}
% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease>
+%<latexrelease>\let\maybe@update@bfseries@defaults\@undefined
+%<latexrelease>\let\maybe@update@mdseries@defaults\@undefined
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\bfseries{%
+%<latexrelease> \not@math@alphabet\bfseries\mathbf
+%<latexrelease> \expand@font@defaults
+%<latexrelease> \ifx\bfdefault\bfdefault@previous\else
+%<latexrelease> \expandafter\def\expandafter\bfdefault
+%<latexrelease> \expandafter{\bfdefault\@empty}%
+%<latexrelease> \let\bfdefault@previous\bfdefault
+%<latexrelease> \let\bfseries@rm\bfdef@ult
+%<latexrelease> \let\bfseries@sf\bfdef@ult
+%<latexrelease> \let\bfseries@tt\bfdef@ult
+%<latexrelease> \UseHook{bfseries/defaults}%
+%<latexrelease> \fi
+%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
+%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
+%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
+%<latexrelease> \else \fontseries\bfdefault
+%<latexrelease> \fi\fi\fi
+%<latexrelease> \UseHook{bfseries}%
+%<latexrelease> \selectfont
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\mdseries{%
+%<latexrelease> \not@math@alphabet\mdseries\relax
+%<latexrelease> \expand@font@defaults
+%<latexrelease> \ifx\mddefault\mddefault@previous\else
+%<latexrelease> \expandafter\def\expandafter\mddefault\expandafter{\mddefault\@empty}%
+%<latexrelease> \let\mddefault@previous\mddefault
+%<latexrelease> \let\mdseries@rm\mddef@ult
+%<latexrelease> \let\mdseries@sf\mddef@ult
+%<latexrelease> \let\mdseries@tt\mddef@ult
+%<latexrelease> \UseHook{mdseries/defaults}%
+%<latexrelease> \fi
+%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
+%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
+%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
+%<latexrelease> \else \fontseries\mddefault
+%<latexrelease> \fi\fi\fi
+%<latexrelease> \UseHook{mdseries}%
+%<latexrelease> \selectfont
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease>
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\bfseries{%
+%<latexrelease> \not@math@alphabet\bfseries\mathbf
+%<latexrelease> \expand@font@defaults
+%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
+%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
+%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
+%<latexrelease> \else \fontseries\bfdefault
+%<latexrelease> \fi\fi\fi
+%<latexrelease> \selectfont
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\mdseries{%
+%<latexrelease> \not@math@alphabet\mdseries\relax
+%<latexrelease> \expand@font@defaults
+%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
+%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
+%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
+%<latexrelease> \else \fontseries\mddefault
+%<latexrelease> \fi\fi\fi
+%<latexrelease> \selectfont
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\bfseries
+%<latexrelease> {\not@math@alphabet\bfseries\mathbf
+%<latexrelease> \fontseries\bfdefault\selectfont}
+%<latexrelease>\DeclareRobustCommand\mdseries
+%<latexrelease> {\not@math@alphabet\mdseries\relax
+%<latexrelease> \fontseries\mddefault\selectfont}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+
+
+
+
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\expand@font@defaults}{Custom series with hooks}%
+% \end{macrocode}
+
+
+
+% \begin{macro}{\expand@font@defaults}
+% \begin{macro}{\rm@def@ult}
+% \begin{macro}{\sf@def@ult}
+% \begin{macro}{\tt@def@ult}
+% \begin{macro}{\md@def@ult}
+% \begin{macro}{\bf@def@ult}
+%
+% The family specific defaults are fully expanded, i.e., they are
+% defined via \cs{edef} inside \cs{DeclareFontSeriesDefault}.
+% However, the overall defaults, e.g., \cs{bfdefault} may have been
+% redefined by the user and thus may not be fully expanded. So to
+% enable reliable comparison we make expanded versions of
+% them. That we rerun each time. The alternative would be to only
+% allow for changes before begin document.
+% \begin{macrocode}
+\def\expand@font@defaults{%
+ \edef\rmdef@ult{\rmdefault}%
+ \edef\sfdef@ult{\sfdefault}%
+ \edef\ttdef@ult{\ttdefault}%
+% \end{macrocode}
+% The series defaults may contain some surplus \texttt{m} that we
+% need to drop here.
+% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{bfdef@ult}
+% and \cs{mddef@ult} (gh/291)}
+% \begin{macrocode}
+ \series@maybe@drop@one@m\bfdefault\bfdef@ult
+ \series@maybe@drop@one@m\mddefault\mddef@ult
+% \end{macrocode}
+% Formats that set up parallel fonts, e.g., for Japanese, can use
+% this hook to add additional code here.
+% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)}
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+ \UseHook{expand@font@defaults}%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+
% \begin{macro}{\rmfamily}
% Here are the document level commands for changing the main font
@@ -1094,7 +1306,7 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2020/02/02}%
-%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease> {\expand@font@defaults}{Custom series with hooks}%
%<latexrelease>
%<latexrelease>\def\expand@font@defaults{%
%<latexrelease> \edef\rmdef@ult{\rmdefault}%
@@ -1105,27 +1317,6 @@
%<latexrelease> \edef\famdef@ult{\familydefault}%
%<latexrelease>}
%<latexrelease>
-%<latexrelease>\DeclareRobustCommand\bfseries{%
-%<latexrelease> \not@math@alphabet\bfseries\mathbf
-%<latexrelease> \expand@font@defaults
-%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
-%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
-%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
-%<latexrelease> \else \fontseries\bfdefault
-%<latexrelease> \fi\fi\fi
-%<latexrelease> \selectfont
-%<latexrelease>}
-%<latexrelease>
-%<latexrelease>\DeclareRobustCommand\mdseries{%
-%<latexrelease> \not@math@alphabet\mdseries\relax
-%<latexrelease> \expand@font@defaults
-%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
-%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
-%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
-%<latexrelease> \else \fontseries\mddefault
-%<latexrelease> \fi\fi\fi
-%<latexrelease> \selectfont
-%<latexrelease>}
%<latexrelease>
%<latexrelease>\DeclareRobustCommand\rmfamily{%
%<latexrelease> \not@math@alphabet\rmfamily\mathrm
@@ -1152,7 +1343,7 @@
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease> {\expand@font@defaults}{Custom series with hooks}%
%<latexrelease>
%<latexrelease>\let\expand@font@defaults\@undefined
%<latexrelease>
diff --git a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
index c6aec105ba5..f562a4fa907 100644
--- a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
@@ -495,7 +495,7 @@
\delayed@f@adjustment
% \end{macrocode}
% We then check if the resulting cominbation is valid but for this
-% we have to make sure the the appropiate \texttt{.fd} is loaded if
+% we have to make sure that the appropiate \texttt{.fd} is loaded if
% that hasn't happened so far.
% \begin{macrocode}
\maybe@load@fontshape
diff --git a/Master/texmf-dist/source/latex/base/lthooks.dtx b/Master/texmf-dist/source/latex/base/lthooks.dtx
index 20e172a57f2..5b3d80e9844 100644
--- a/Master/texmf-dist/source/latex/base/lthooks.dtx
+++ b/Master/texmf-dist/source/latex/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.0s}
+\def\lthooksdate{2021/09/28}
% \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,20 @@
% 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
-% generic \hook{cmd} hook was already explicitly declared before.
-%
-% Normally \cs{hook_new:n} should be used instead.
+% This is like \cs{hook_new:n} but it does nothing if the hook was previously
+% declared with \cs{hook_new:n}. This declaration should be used
+% only in special situations, e.g., when a command from another package
+% needs to be altered and it is not clear whether a
+% generic \hook{cmd} hook (for that command) has been previously
+% explicitly declared.
+%
+% Normally \cs{hook_new:n} should be used instead of this.
% \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 +1033,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 +1049,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 +1166,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 +1325,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 +1343,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 +1446,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 +1455,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 +1466,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 +1522,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 +1631,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 +1648,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 +1701,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 +1760,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 +1868,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 +1877,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 +1929,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 +2024,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 +2057,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 +2074,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 +2114,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 +2213,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 +2266,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 +2309,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 +2345,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 +2355,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 +2398,8 @@
% \end{macrocode}
% \end{macro}
%
-%
-%
+%
+%
% \begin{macro}{\@@_make_usable:n}
%
% This initializes all hook data structures for the hook but if
@@ -2315,7 +2473,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 +2565,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 +2583,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 +2607,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 +2617,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 +2665,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 +2734,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 +2744,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 +2756,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 +2780,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 +2823,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 +2977,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 +3093,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}
%
@@ -2866,44 +3139,43 @@
% component to see if we have to make a reversed hook. In either case
% the function returns \meta{true} for a generic hook and \meta{false}
% in other cases.
+%
+% \changes{v1.0s}{2021/09/28}
+% {Correct usage of older \cs{@@_if_file_hook:wTF} (gh/675)}
% \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
+%<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 +3185,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 +3195,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 +3339,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 +3449,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 +3539,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 +3556,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 +3626,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 +3769,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 +3810,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 +3862,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 +3873,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 +3888,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 +3977,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 +3997,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 +4013,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 +4039,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 +4060,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 +4077,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 +4101,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 +4119,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 +4276,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 +4287,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 +4349,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 +4395,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 +4612,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 +4651,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 +4686,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 +4768,123 @@
% \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}
%
+% \changes{v1.0s}{2021/09/28}
+% {Correct usage of older \cs{@@_if_file_hook:wTF} (gh/675)}
% \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
+%<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 +4972,8 @@
}
% \end{macrocode}
% \end{macro}
-%
-%
-%
+%
+%
% \begin{macro}[pTF]{\@@_if_declared:n}
%
% Internal test to check if the hook was officially declared with
@@ -4526,28 +4993,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 +5075,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 +5083,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 +5116,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 +5128,7 @@
'unrelated'.
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\msg_new:nnnn { hooks } { misused-top-level }
{
@@ -4651,7 +5166,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 +5176,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 +5218,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 +5257,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 +5282,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 +5294,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 +5322,6 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
%
%
@@ -4961,7 +5345,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 +5355,7 @@
%
%
% \begin{macro}{\DeclareHookRule}
-%
+%
% \begin{macrocode}
\NewDocumentCommand \DeclareHookRule { m m m m }
{ \hook_gset_rule:nnnn {#1}{#2}{#3}{#4} }
@@ -5001,7 +5385,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 +5409,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 +5557,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 +5594,6 @@
% \Finale
%
%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/Master/texmf-dist/source/latex/base/ltluatex.dtx b/Master/texmf-dist/source/latex/base/ltluatex.dtx
index 3b9a3377312..258ac482977 100644
--- a/Master/texmf-dist/source/latex/base/ltluatex.dtx
+++ b/Master/texmf-dist/source/latex/base/ltluatex.dtx
@@ -28,7 +28,7 @@
\ProvidesFile{ltluatex.dtx}
%</driver>
%<*tex>
-[2021/04/18 v1.1t
+[2021/10/15 v1.1v
%</tex>
%<plain> LuaTeX support for plain TeX (core)
%<*tex>
@@ -912,12 +912,14 @@ local luatexbase = luatexbase
% \end{macro}
%
% Some Lua best practice: use local versions of functions where possible.
+% \changes{v1.1u}{2021/08/11}{Define missing local function}
% \begin{macrocode}
local string_gsub = string.gsub
local tex_count = tex.count
local tex_setattribute = tex.setattribute
local tex_setcount = tex.setcount
local texio_write_nl = texio.write_nl
+local flush_list = node.flush_list
% \end{macrocode}
% \changes{v1.0i}{2015/11/29}{Declare this as local before used in the module error definitions (PHG)}
% \begin{macrocode}
@@ -1413,6 +1415,7 @@ local callbacktypes = callbacktypes or {
% \changes{v1.1j}{2019/06/18}{font\_descriptor\_objnum\_provider added}
% \changes{v1.1l}{2020/02/02}{glyph\_info added}
% \changes{v1.1t}{2021/04/18}{input\_level\_string added}
+% \changes{v1.1v}{2021/10/15}{provide\_charproc\_data added}
% \begin{macrocode}
define_font = exclusive,
glyph_info = exclusive,
@@ -1421,6 +1424,7 @@ local callbacktypes = callbacktypes or {
make_extensible = exclusive,
font_descriptor_objnum_provider = exclusive,
input_level_string = exclusive,
+ provide_charproc_data = exclusive,
% \end{macrocode}
% \changes{v1.0m}{2016/02/11}{pdf\_stream\_filter\_callback removed}
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltmath.dtx b/Master/texmf-dist/source/latex/base/ltmath.dtx
index aadb96fb023..59e0d89a106 100644
--- a/Master/texmf-dist/source/latex/base/ltmath.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmath.dtx
@@ -38,7 +38,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmath.dtx}
- [2021/04/20 v1.2i LaTeX Kernel (Math Setup)]
+ [2021/10/14 v1.2j LaTeX Kernel (Math Setup)]
% \iffalse
%</driver>
%
@@ -915,10 +915,13 @@
% whole display. Note that we can't use \cs{refstepcounter} as this
% results in |\@currentlabel| getting restored at the wrong and
% thus always writing the first label to the \texttt{.aux} file.
+% \changes{v1.2j}{2021/10/14}
+% {Explicitly set \cs{@currentcounter} (gh/687)}
% \begin{macrocode}
\def\eqnarray{%
\stepcounter{equation}%
\def\@currentlabel{\p@equation\theequation}%
+ \def\@currentcounter{equation}%
\global\@eqnswtrue
\m@th
\global\@eqcnt\z@
@@ -1231,10 +1234,13 @@
%
% \begin{environment}{eqnarray}
% The \textsf{eqnarray} environment
+% \changes{v1.2j}{2021/10/14}
+% {Explicitly set \cs{@currentcounter} (gh/687)}
% \begin{macrocode}
\renewenvironment{eqnarray}{%
\stepcounter{equation}%
\def\@currentlabel{\p@equation\theequation}%
+ \def\@currentcounter{equation}%
\global\@eqnswtrue\m@th
\global\@eqcnt\z@
\tabskip\mathindent
diff --git a/Master/texmf-dist/source/latex/base/ltmiscen.dtx b/Master/texmf-dist/source/latex/base/ltmiscen.dtx
index 8bae3f9bfa3..6cc58907a0d 100644
--- a/Master/texmf-dist/source/latex/base/ltmiscen.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmiscen.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmiscen.dtx}
- [2021/02/08 v1.1y LaTeX Kernel (Misc. Environments)]
+ [2021/06/05 v1.1z LaTeX Kernel (Misc. Environments)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltmiscen.dtx}
@@ -1471,12 +1471,13 @@
\def\@sverb#1{\if\noexpand#1 \expandafter\@sverb\else\@@sverb{#1}\fi}
% \end{macrocode}
%
+% \changes{v1.1z}{2021/06/05}{Normalize error message}
% \begin{macrocode}
\def\@@sverb#1{%
\catcode`#1\active
\lccode`\~`#1%
\gdef\verb@balance@group{\verb@egroup
- \@latex@error{\noexpand\verb illegal in command argument}\@ehc}%
+ \@latex@error{\noexpand\verb illegal in argument}\@ehc}%
\aftergroup\verb@balance@group
\lowercase{\let~\verb@egroup}%
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltoutenc.dtx b/Master/texmf-dist/source/latex/base/ltoutenc.dtx
index eb2ecd1e537..61ea381823c 100644
--- a/Master/texmf-dist/source/latex/base/ltoutenc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltoutenc.dtx
@@ -44,7 +44,7 @@
%<*driver>
% \fi
\ProvidesFile{ltoutenc.dtx}
- [2021/04/29 v2.0v LaTeX Kernel (font encodings)]
+ [2021/10/16 v2.0x LaTeX Kernel (font encodings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutenc.dtx}
@@ -199,7 +199,7 @@
% commands, such as accents. It also contains the code for some of
% the encoding files, including |omlenc.def|,
% |omsenc.def|, |t1enc.def| and |ot1enc.def| files, which define
-% the |OLM|,
+% the |OML|,
% |OMS|, |T1| and |OT1| encodings, and the |fontenc| package
% for selecting encodings.
%
@@ -845,10 +845,11 @@
% We also ignore \cs{ignorespaces} which has the same issue and may
% show up as part of \cs{normalfont} if that is used.
% \changes{v2.0m}{2019/12/18}{Avoid code that breaks \cs{accent}}
+% \changes{v2.0x}{2021/10/16}{Dont set \cs{spacefactor in math mode gh/643}}
% \begin{macrocode}
\let\maybe@load@fontshape\relax
\let\ignorespaces\relax
- \accent#1 #2\egroup\spacefactor\accent@spacefactor}
+ \accent#1 #2\egroup\ifmmode\else\spacefactor\accent@spacefactor\fi}
% \end{macrocode}
%
%
@@ -1783,12 +1784,14 @@
% {Added \cs{ij} and \cs{IJ} from babel. (pr/3771)}
% The dutch language uses the letter `ij'. It is available in
% \texttt{T1} encoded fonts, but not in the \texttt{OT1} encoded
-% fonts. Therefor we fake it for the \texttt{OT1} encoding.
+% fonts. Therefore we fake it for the \texttt{OT1} encoding.
+% \changes{v2.0w}{2021/09/12}{Move zero skip between
+% i and j for hyphenation (gh/658)}
% \begin{macrocode}
\DeclareTextCommand{\ij}{OT1}{%
- \nobreak\hskip\z@skip i\kern-0.02em j\nobreak\hskip\z@skip}
+ \nobreak\hskip\z@skip i\kern-0.02em\nobreak\hskip\z@skip j}
\DeclareTextCommand{\IJ}{OT1}{%
- \nobreak\hskip\z@skip I\kern-0.02em J\nobreak\hskip\z@skip}
+ \nobreak\hskip\z@skip I\kern-0.02em\nobreak\hskip\z@skip J}
% \end{macrocode}
% In the OT1 encoding, \pounds~and \$ share a slot.
% \changes{v1.9y}{2000/01/30}{Use \cs{hmode@bgroup} where applicable
diff --git a/Master/texmf-dist/source/latex/base/ltoutput.dtx b/Master/texmf-dist/source/latex/base/ltoutput.dtx
index b1b3a240965..78b0f2335f8 100644
--- a/Master/texmf-dist/source/latex/base/ltoutput.dtx
+++ b/Master/texmf-dist/source/latex/base/ltoutput.dtx
@@ -30,14 +30,14 @@
%%% From File: ltoutput.dtx
%<flafter>\ProvidesPackage{flafter}
%<fltrace>\ProvidesPackage{fltrace}
-%<flafter,fltrace> [2018/11/28 v1.4d
+%<flafter,fltrace> [2021/07/31 v1.4e
%<flafter> Standard LaTeX floats after reference (FMi)]
%<fltrace> Tracing LaTeX floats algorithm (FMi)]
%
%<*driver>
% \fi
\ProvidesFile{ltoutput.dtx}
- [2021/05/05 v1.4g LaTeX Kernel (Output Routine)]
+ [2021/09/03 v1.4h LaTeX Kernel (Output Routine)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutput.dtx}
@@ -3945,10 +3945,69 @@
\fi
\fi
}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+% \begin{macro}{\ShowFloat}
+% This command provides some information about the contenta of a
+% float register. Float registers have internal names of the form
+% \cs{bx@}\meta{Uppercase-letter(s)-or numbers} and you specify just this
+% letter or letters as the argument, e.g., \verb=\ShowFloat{A}=.
+% (There is not much error recovery if you specify something that
+% isn't a float.)
+% \changes{v1.4g}{2021/07/31}{Macro added}
+% \changes{v1.4h}{2021/09/03}{Renamed, original name never distributed}
+% \begin{macrocode}
%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\ShowFloat}{Show float register contents}%
+\def\ShowFloat#1{\begingroup
+ \let \fl@trace \fl@tracemessage
+ \fl@trace{***Float #1 details:}%
+ \ifcsname bx@#1\endcsname
+ \expandafter\fl@ShowFloat\csname bx@#1\endcsname
+ \else
+ \fl@trace{Not a float!}%
+ \fi
+ \endgroup
+}
+\def\fl@ShowFloat#1{%
+ \fl@traceval{\count#1}% % this here should be interpreted on day
+ \fl@traceval{\ht#1}%
+ \fl@traceval{\dp#1}%
+ \fl@traceval{\wd#1}%
+ {\tracingonline1\showboxbreadth10\showboxdepth3\showbox#1}%
+}
+% \end{macrocode}
+% Here are two definitions from \texttt{fltrace} that make the above
+% code work:
+% \begin{macrocode}
+\def \fl@traceval #1{\fl@trace{\string #1 = \the #1}}
+\def \fl@tracemessage #1{{\let\@elt\@empty\typeout{LaTeX2e: #1}}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\ShowFloat}{Show float register contents}%
+%<latexrelease>
+%<latexrelease>\let\ShowFloat\@undefined
+%<latexrelease>\let\fl@ShowFloat\@undefined
+%<latexrelease>\let\fl@traceval\@undefined
+%<latexrelease>\let\fl@tracemessage\@undefined
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \subsubsection{Float control}
%
% This part implements controllable floats and other changes
@@ -4025,6 +4084,16 @@
% wrong value.\footnote{This is a somewhat questionable design.}
% \begin{macrocode}
\begingroup
+% \end{macrocode}
+% When the user requests \cs{tracefloatvals} then they should show
+% regardless of the tracing state, so locally we make sure that it
+% is activated.
+% \changes{v1.4e}{2021/07/31}{Enable display when doing \cs{tracefloatvals}}
+% \begin{macrocode}
+ \tracefloats
+% \end{macrocode}
+%
+% \begin{macrocode}
\@dblfloatplacement
\@floatplacement
\fl@trace{***Float placement parameters:}%
@@ -4052,6 +4121,7 @@
{trace float vals}%
\def \tracefloatvals{%
\begingroup
+ \tracefloats
\@dblfloatplacement
\@floatplacement
\fl@trace{***Float placement parameters:}%
@@ -4077,6 +4147,10 @@
}
\EndIncludeInRelease
% \end{macrocode}
+%
+%
+%
+%
% We need to make sure that \texttt{fltrace} comes before
% \texttt{flafter} to make the tracing work.
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltpara.dtx b/Master/texmf-dist/source/latex/base/ltpara.dtx
index 5ab52a5e9bc..a2da67198a6 100644
--- a/Master/texmf-dist/source/latex/base/ltpara.dtx
+++ b/Master/texmf-dist/source/latex/base/ltpara.dtx
@@ -14,8 +14,8 @@
%%% From File: ltpara.dtx
%
% \begin{macrocode}
-\def\ltparaversion{v1.0g}
-\def\ltparadate{2021/05/27}
+\def\ltparaversion{v1.0k}
+\def\ltparadate{2021/11/11}
% \end{macrocode}
%<*driver>
\documentclass{l3doc}
@@ -23,6 +23,7 @@
%\usepackage{ltpara}
% Fixing footnotes in functions and variables: this should be in l3doc!
+
\newcommand\fixfootnote[2]{\footnotemark
\AddToHookNext{env/#1/after}{\footnotetext{#2}}}
\AddToHook{env/function/begin}{\def\footnote{\fixfootnote{function}}}
@@ -122,8 +123,8 @@
% \verb=\hbox{a\par b}= is ignored, but \verb=$a\par b$= would complain.
%
% If this primitive ends the paragraph it does some special
-% \enquote{end of horizontal list} processing, then calls \TeX{} paragraph
-% builder that breaks the horizontal list into lines then these
+% \enquote{end of horizontal list} processing, then calls \TeX{}’s paragraph
+% builder; this breaks the horizontal list into lines and then these
% lines are added as boxes to the enclosing vertical list and
% \TeX{} returns to vertical mode.
%
@@ -133,13 +134,14 @@
% automatically changed to a \cs{par} command which is then
% executed. The other possibility is that \TeX{} encounters a
% command which is incompatible with horizontal processing, e.g.,
-% \cs{vskip} (a request for adding vertical space). In such case it
+% \cs{vskip} (a request for adding vertical space). In such cases it
% silently backs up, and inserts a \cs{par} in the hope that this
-% gets it out of horizontal mode and makes the offending command
+% gets it out of horizontal mode and makes the vertical command
% acceptable.
% The important point to note here is that \TeX{} really inserts
-% the command \cs{par} which can be redefined. Thus, it may not have
+% the command with the name \cs{par}, which can be redefined.
+% Thus, it may not have
% its original \enquote{primitive} meaning and therefore may not end the
% horizontal list and call the paragraph builder. This approach
% offers some flexibility but also allows you to easily produce a
@@ -151,31 +153,30 @@
% then sees \cs{vskip} and inserts \cs{par} to end the
% paragraph. But this now only runs \cs{relax} so nothing changes
% and \cs{vskip} is read again, issues a \cs{par} which \ldots. In
-% short, it takes a plain \TeX{} document with five tokens to run
-% forever (as not even memory is consumed and therefore eventually
+% short, it only takes a plain \TeX{} document with five tokens to run
+% forever (since no memory is consumed and therefore eventually
% exhausted).
%
-% There are no other ways than changing \cs{par} to gain control at
+% There is no way other than changing \cs{par} to gain control at
% the end of a paragraph, i.e., there is no token list like
-% \cs{everypar} that is inserted, i.e., the only way to change the
-% default behavior is to modify the action that \cs{par} executes
+% \cs{everypar} that is inserted. Hence the only way to change the
+% default behavior is to modify the action that \cs{par} executes,
% with similar issues as outlined before: different processes need
% to ensure that they do not overwrite their modifications or
% worse, think that the \cs{par} in front of them is the engine
% primitive while in fact it has already been changed by other
% code.
%
-%
% To make matters slightly worse there are a few places where
% \TeX{} handles the situation differently (most likely for speed
% reasons back when computers were much slower). If \TeX{} finds
% itself in unrestricted horizontal mode at the end of building a
-% vertical box (or an \cs{insert}, \cs{vadjust} or at the end of
+% vertical box (for an \cs{insert}, \cs{vadjust} or
% executing the output routine code), it will finish the horizontal
% list not by issuing a \cs{par} command (which would be consistent
-% with all other places, but by simply executing the primitive version
-% of \cs{par} regardless of the definition that \cs{par} has at the
-% time.
+% with all other places) but by simply executing the primitive meaning
+% of \cs{par}, regardless of the actual definition that \cs{par}
+% has at the time.
%
% Thus, if you have carefully crafted a redefined \cs{par} to execute
% some special actions at the end of a paragraph and you write
@@ -183,27 +184,28 @@
%\begin{verbatim}
% \vbox{Some paragraph ... text.}
%\end{verbatim}
-% you will find that your code has never run for the last paragraph
+% you will find that your code does not get run for the last paragraph
% in that box. \LaTeX{} avoids this problem, by making sure that
-% all its boxes (such as \cs{parbox} or the \env{minipage}
+% its boxes (such as \cs{parbox} or the \env{minipage}
% environment, etc.) all internally add an explicit \cs{par} at the
% end so that such code is run and \TeX{} finds itself in vertical
% mode already without the need to start up the paragraph builder
% internally. But, of course, this only works for boxes under direct
-% control of the \LaTeX{} kernel, if some package uses low-level
+% control of the \LaTeX{} kernel; if some package uses low-level
% \cs{vbox}es without adding this precaution the \TeX{}
% optimization kicks in and no special \cs{par} code is executed.
%
% And there is another optimization that is painful: if a paragraph
% is interrupted by a mathematical display, e.g., \verb=\[...\]= in
% \LaTeX{} or \verb=$$...$$= in plain \TeX{}, then \TeX{} will
-% resume horizontal mode afterward, i.e., build a new horizontal
-% list (without inserting an indentation box or \cs{everypar} at
-% that point). However, if that list immediately ends with an
+% resume horizontal mode afterward, i.e., it will start to build
+% a new horizontal
+% list without inserting an indentation box or \cs{everypar} at
+% that point. However, if that list immediately ends with an
% explicit or implicit \cs{par} then \TeX{} will simply throw away
% this \enquote{null} paragraph and not do its usual \enquote{end
-% of horizontal list} processing, so this special case need to be
-% accounted for when introducing some extended processing.
+% of horizontal list} processing, so this special case also needs to be
+% accounted for when introducing any extended processing.
%
%
%
@@ -214,8 +216,8 @@
% the start and end of the paragraph processing. The public hooks
% can be used by packages (or by the user in the preamble or
% within the document) and using the hook mechanisms it is possible
-% to reorder or arrange code from different packages in a way that
-% it can safely coexist.
+% to reorder or arrange code from different packages in such a way that
+% these can safely coexist.
%
% To make that happen we have to make use of the basic
% functionality that is offered by \TeX{}, e.g., we install
@@ -248,7 +250,7 @@
% Fortunately, \LaTeX{} has already redefined \cs{par} for its own
% purposes. As a result there aren't many packages that attempt to
% change \cs{par}, because without a lot of extra care that would
-% fail miserably. But bottom line, if you load a package that
+% fail miserably. But the bottom line is that, if you load a package that
% alters \cs{par} then the end of paragraph hooks are most likely
% not executing while that redefinition is
% active.\footnote{Similarly to the \cs{everypar} situation, the
@@ -326,7 +328,7 @@
%
% This hook is executed at the end of a paragraph when \TeX{} is
% ready to return to vertical mode and after it has removed the
-% last horizontal glue (but not kern) placed on the horizontal
+% last horizontal glue (but not any kerns) placed on the horizontal
% list. The code is still executed in horizontal mode so it is
% possible to add further horizontal material at this point, but
% it should not alter the mode (even a temporary exit from
@@ -415,20 +417,20 @@
% \subsection{Altered and newly provided commands}
%
% \begin{function}{\par,\endgraf,\para_end:}
-% An explicit request for ending a paragraph is known in plain
-% \TeX{} under the name \cs{endgraf} where it simply calls the
-% paragraph primitive (regardless of what \cs{par} may have as its
-% current definition). In \LaTeX{} \cs{endgraf} with that behavior
-% was also made available.
+% An explicit request for ending a paragraph is provided in plain
+% \TeX{} under the name \cs{endgraf}, which simply uses the
+% primitive meaning (regardless of what \cs{par} may have as its
+% current definition). In \LaTeX{} \cs{endgraf} (with that behavior)
+% was originally also available.
%
% With the new paragraph handling in \LaTeX{}, ending a paragraph
% means a bit more than just calling the engine's paragraph
% builder: the process also has to add any hook code for the end of
% a paragraph. Thus
% \cs{endgraf} was changed to provide this additional functionality
-% (and so by extension \cs{par} subject to its current meaning).
+% (along with \cs{par} remaining subject to its current meaning).
%
-% The \pkg{expl3} name for the functionality is \cs{para_end:}.
+% The \pkg{expl3} name for this functionality is \cs{para_end:}.
% \end{function}
%
% \begin{quote}
@@ -468,7 +470,7 @@
%
% The commands \cs{RawIndent} and \cs{RawNoindent} are not meant
% for normal paragraph building (where the result is a textual
-% paragraph in the the traditional meaning of the word), but for
+% paragraph in the traditional meaning of the word), but for
% special cases where \TeX{}'s low-level algorithm is used to
% achieve special effects, but where the result is not a
% \enquote{paragraph}.
@@ -538,7 +540,7 @@
% sequence numbers. This is most easily done using \pkg{expl3}
% functions, so we switch over. This is not a very general
% implementation, just enough for what we need and a bit of
-% \LaTeXe{} thrown in as well. When popping the result gets stored
+% \LaTeXe{} thrown in as well. When popping, the result gets stored
% in \cs{paracntvalue} and the \cs{ERROR} should never happen
% because it means we have tried to pop from an empty stack.
%\begin{verbatim}
@@ -602,8 +604,8 @@
%
% \subsubsection{Mark the first paragraph of each \env{itemize}}
%
-% The code for this is rather simple. We apply hook code that is
-% executed only once inside a hook that is executed at the begin of
+% The code for this is rather simple. We supply some code that is
+% executed only once inside a hook at the start of
% each \env{itemize}. We explicitly change the color back and
% forth so that we don't introduce grouping around the paragraph.
%\begin{verbatim}
@@ -629,7 +631,7 @@
% \subsubsection{Glue items between paragraphs (found with \pkg{fancypar})}
%
% In the past \LaTeX{} placed two glue items between two
-% consecutive paragraph, e.g.,
+% consecutive paragraphs, e.g.,
%\begin{verbatim}
% text1 \par text2 \par
%\end{verbatim}
@@ -644,12 +646,12 @@
% \glue(\parskip) 0.0
% \glue(\baselineskip) 5.16669
%\end{verbatim}
-% The reason is that we generate a \enquote{fake}'' paragraph to
+% The reason is that we generate a \enquote{fake} paragraph to
% gain control and safely add the early hooks, but this generates
% an additional glue item. That item doesn't contribute anything
-% vertically but ifsomebody writes code the unravels a constructed
+% vertically but if somebody writes code that unravels a constructed
% list using \cs{lastbox}, \cs{unskip} and \cs{unpenalty} then the
-% code has to remove one additional glue item or else will fail.
+% code has to remove one additional glue item or else it will fail.
%
% ^^A \subsubsection{}
@@ -828,8 +830,8 @@
%
% But if we have already replaced it by a token register then all
% they do is to give that token register a new name. Thus our code
-% in \cs{tex_everypar:D} would call \cs{everypar} (which is their
-% now token register) and the code that they added ends up in our
+% in \cs{tex_everypar:D} would call \cs{everypar} (which is now their
+% token register) and the code that they added ends up in our
% token register which is then never used at all. A bit mind
% boggling I guess.
%
@@ -927,7 +929,7 @@
% \end{itemize}
%
% Unfortunately, \TeX{} has some (these days) unnecessary
-% optimization: if a \cs{vbox} ends and \TeX{} is still in
+% optimizations: if a \cs{vbox} ends and \TeX{} is still in
% horizontal mode it simply exercises the paragraph builder instead
% of issuing a \cs{par}. It is therefore necessary for \LaTeX{} to
% ensure that this case doesn't happen and all boxes internally
@@ -940,11 +942,11 @@
% \texttt{latex.ltx}. For this \LaTeXe{} code has the following
% conventions: \cs{@@@@par} and \cs{endgraf} both refer to the
% default meaning (in the past this was the initex primitive) while
-% \cs{par} is the current meaning which may does something else.
+% \cs{par} is the current meaning which maybe does something else.
%
%
-% We are now going to change this default meaning to run
-% \cs{para_end:} instead, which ultimately executes the initex
+% We are now going to change this default meaning to instead run
+% \cs{para_end:}, which ultimately executes the initex
% primitive but additionally adds our hooks when appropriate.
% This way the change is again transparent to the legacy \LaTeXe{}
% code.
@@ -953,110 +955,158 @@
% primitive and we achieve this by simply expanding it to the
% primitive which is available to us as \cs{tex_par:D}. This way we
% don't have to care about whether \TeX{} just does nothing (e.g.,
-% if in vertical mode already) or generate an error, etc.
+% if in vertical mode already) or generates an error, etc.
% \begin{macrocode}
\cs_new_protected:Npn \para_end: {
% \end{macrocode}
%
+% CCC Maybe needs more explanation.
+% TEMP NOTE: What should happen if in outer hmode with an empty hlist?
+%
% The only case we care about is when we are in horizontal mode
% (i.e., doing typesetting) and not also in inner mode (i.e.,
% making paragraphs and not building an \cs{hbox}.
-% \begin{macrocode}
+%\begin{verbatim}
% \bool_lazy_and:nnT
% { \mode_if_horizontal_p: }
% { \bool_not_p:n { \mode_if_inner_p: } }
% { ...
-% \end{macrocode}
+%\end{verbatim}
% Since this is executed for each and every paragraph in a document
-% we try to stay a fast as possible, So we are aren't using the
+% we try to stay as fast as possible, so we do not use the
% above construct but two conditionals instead. Using low-level
% \cs{if_mode...} conditions would be even faster but has the
% danger to conflict with conditionals in the user hooks.
+%
+% If \cs{para_end:} is executed while \TeX{} is currently doing a
+% low-level assignment the test for horizontal mode may get
+% executed as part of the assignment. That is normally not an issue
+% but we just found one case where it is:
+%\begin{verbatim}
+% \afterassignment\lst@vskip\@tempskipa \z@ \par
+%\end{verbatim}
+% If \TeX{} is in hmode while that assignment happens then the
+% \cs{par} is seen in hmode because in the above case the
+% assignment may not be finished (one should have used \cs{z@skip}) and
+% the \cs{lst@vskip} will get inserted into the middle of the
+% conditional. The \cs{lst@vskip} then changes to vmode and you get
+% a surprising error about the \texttt{para/end} hook having
+% changed modes even if you don't have any hook code(!): it is
+% the inserted \cs{lst@vskip} that is actually causing the change of
+% mode.This is what happened
+% when the output routines got started while a \texttt{lstlisting}
+% environment (that redefines \cs{vskip} in this way) was
+% active. This is really faulty coding, but we try to be proactive
+% and guard the conditional so that any scanning is first stopped, thus:
+% \begin{macrocode}
+ \scan_stop:
+% \end{macrocode}
+%
% \begin{macrocode}
\mode_if_horizontal:TF {
\mode_if_inner:F {
% \end{macrocode}
% In that case the action of the primitive would be to remove the
-% last glue (not kern) from the horizontal list constructed to form
-% a paragraph then append the a penalty of 10000 and the
-% \cs{parfillskip} at the end and pass the whole list to the
-% paragraph builder which breaks it into lines and \TeX{} then
+% last glue (but no kerns) from the horizontal list (constructed to form
+% a paragraph) and then to append a penalty of 10000 and the
+% \cs{parfillskip}; it then passes the whole list to the
+% paragraph builder, which breaks it into lines and \TeX{} then
% returns to vertical mode.
%
-% What we want to do instead is to add our hook code at the end of
-% the horizontal list before that happens and the code is passed to
-% the paragraph builder. If there was a glue item at the end then
+% What we want to do is to add this hook code at the end of
+% the horizontal list before any of the above happens.
+% If there was a glue item at the end of the list then
% it should get removed before the hook code gets added so we have
-% to arrange for its removal ourselves.
+% to arrange for this removal.
+%
+% As in other simular cases, it maybe best to add here
+% a \cs{nobreak} in case the hook itself adds glue and thus
+% creates a non-explicit and unwanted potential breakpoont.
+% On the other hand (as has been argued) the code in the hook
+% should perhaps have the responsibility for adding such a
+% guard penalty in this casse.
+% This needs further analysis and decisions (as in emails).
+%
+% In either case, good documentation of these hooks is essential,
+% covering what the hook may or should provide and all
+% such related considerations convernimg the content.
%
% There is not much point in checking if there was really a glue
% item at the end of the horizontal list, instead we simply try to
-% remove one using \cs{tex_unskip:D}, if there wasn't one this will
+% remove one using \cs{tex_unskip:D}: if there wasn't one this will
% do nothing.
% \begin{macrocode}
\tex_unskip:D
% \end{macrocode}
-% The we execute the public hook (which may add final typesetting
-% material) followed by the kernel hook we need for adding tagging
+% We then execute the public hook (which may add some final typeset
+% material) followed by the kernel hook that we need for adding tagging
% support. None of this is supposed to change the mode---at the
% moment we make only a very simple test for this, more devious
-% changes go unnoticed, but too bad, that will then probably
-% badly backfire.
+% changes go unnoticed, but too bad as they will then probably
+% backfire badly.
% \begin{macrocode}
\hook_use:n{para/end}
\@kernel@after@para@end
\mode_if_horizontal:TF {
% \end{macrocode}
% The final action (before getting to the point where
-% \cs{tex_par:D} is called) is to add a kern item so that the
-% primitive is prevented from removing glue (if there was some). If
-% we don't do this and the
-% horizontal list ended in several glue items we would end up with
-% removing two instead of just the last one, which would be wrong.
-% We use a kern as that is minimally faster.
+% \cs{tex_par:D} is called) is to add an extra glue item so that the
+% primitive is prevented from removing intended glue
+% (if there was some). If we don't do this and the
+% horizontal list ends in several glue items we would end up removing
+% two glue items instead of just the last one, which would be wrong.
+% We use glue (rather than a kern) as that will be removed by the
+% primitive.
%
% There is however one other \TeX{} optimization that hurts: in a
-% sequence like this \verb=$$ ... $$ \par= \TeX{} will be in
+% sequence like this \verb=$$ ... $$ \par= (with \cs{par} being the primitive)
+% \TeX{} will be in
% horizontal mode after the display, ready to receive further
% paragraph text, but since the \cs{par} follows immediately there
% is a ``null'' paragraph at the end and \TeX{} simply throws that
-% away. The space between \verb=$$= and \cs{par} got already
+% away.
+% The space between \verb=$$= and \cs{par} got already
% dropped during the display processing so the \cs{par} is not
% removing any space and appending \cs{parfillskip}, instead it
-% simply goes silently to vmode. Now if we would had added something (to
+% simply goes silently to vmode.
+%
+% Now if we would have added something (to
% prevent glue removal) that would look to \TeX{} like material
% after the display and so we would end up with an empty paragraph
-% just containing \cs{parfillskip}.
+% just containing a penalty and \cs{parfillskip}.
%
-% We therefore check if the current hlist is empty
-% (\cs{tex_lastnodetype:D} has the value \texttt{-1} and
-% only if not we add our kern.
+% We therefore check if the current hlist does end in glue
+% (\cs{tex_lastnodetype:D} has the value \texttt{11}) and
+% if so we add a zero-length guard skip which will be removed by the
+% following \cs{tex_par:D}.
+% \changes{v1.0i}{2021/09/18}{Use skip rather than kern as guard.}
% \begin{macrocode}
- \if_int_compare:w 0 < \tex_lastnodetype:D
- \tex_kern:D \c_zero_dim
+ \if_int_compare:w 11 = \tex_lastnodetype:D
+ \tex_hskip:D \c_zero_dim
\fi:
% \end{macrocode}
% To run the \hook{para/after} hook we first end the
% paragraph. This means that the \cs{tex_par:D} at the very end is
% unnecessary but executing it there unnecessarily is better than
-% having code that test for all the different mode possibilities.
+% having code that tests for all the different mode possibilities.
% \begin{macrocode}
\tex_par:D
\hook_use:n{para/after}
\@kernel@after@para@after
}
% \end{macrocode}
-% If we haven't been in horizontal mode then the earlier hook
-% \hook{para/end} is at fault and we report that.
+% If we were not horizontal mode (the F case from above)
+% then the earlier hook
+% \hook{para/end} must have been at fault, so we report that.
% \begin{macrocode}
{ \msg_error:nnnn { hooks }{ para-mode }{end}{horizontal} }
% \end{macrocode}
% Finally close out the nested conditionals.
% \begin{macrocode}
}
- }
+ }
% \end{macrocode}
-%
+% And then we can use the primitive to truly end the paragraph.
% \begin{macrocode}
\tex_par:D
}
@@ -1090,7 +1140,7 @@
\@@_handle_indent:
\the\everypar }
}
- { \msg_error:nn { kernel }{ raw-para } }
+ { \msg_error:nn { latex2e }{ raw-para } }
\tex_indent:D
}
% \end{macrocode}
@@ -1103,7 +1153,7 @@
\tex_everypar:D { \g_@@_standard_everypar_tl }
\the\everypar }
}
- { \msg_error:nn { kernel }{ raw-para } }
+ { \msg_error:nn { latex2e }{ raw-para } }
\tex_noindent:D
}
% \end{macrocode}
@@ -1133,10 +1183,11 @@
% \begin{macro}[int]{\@@par}
%
% Having the new default definition for \cs{par} we also have to
-% set it up so that it gets used. This is needed in three places
+% set it up so that it gets used. This involves three commands:
% \cs{par}, \cs{@@par} (to which \LaTeX{} resets \cs{par}
-% occasionally) and \cs{endgraf} which is another name for the
+% occasionally) and \cs{endgraf}, which is another name for the
% ``default'' action of \cs{par}.
+%
% \begin{macrocode}
\cs_set_eq:NN \par \para_end:
\cs_set_eq:NN \@@par \para_end:
@@ -1161,7 +1212,7 @@
% The first argument is the hook name second the mode
% it should have stayed in but didn't.
%
-% \begin{macrocode}
+% \begin{macrocode}
\msg_new:nnnn { hooks } { para-mode }
{
Illegal~mode~ change~ in~ hook~ 'para/#1'.\\
@@ -1175,10 +1226,11 @@
}
% \end{macrocode}
%
+% \changes{v1.0i}{2021/08/27}{Internal message name changes}
% And here is one used in the \enquote{raw} commands when they are
-% used outside of vertical mode.
+% used outside of vertical mode.
% \begin{macrocode}
-\msg_new:nnnn { kernel } { raw-para }
+\msg_new:nnnn { latex2e } { raw-para }
{
Not~ in~ vertical~ mode.
}
@@ -1206,7 +1258,17 @@
%<latexrelease>\cs_set_eq:NN \par \tex_par:D
%<latexrelease>\cs_set_eq:NN \@@par \tex_par:D
%<latexrelease>\cs_set_eq:NN \endgraf \tex_par:D
-%<latexrelease>
+%<latexrelease>
+% \end{macrocode}
+% We also need to clean up the primitive ``everypar'' as that
+% should no longer execute any code by default. And, of course,
+% make \cs{everypar} become the primitive again.
+% \changes{v1.0k}{2021/10/19}{Remove content from \cs{tex_everypar:D}
+% on rollback}
+% \begin{macrocode}
+%<latexrelease>\tex_everypar:D {}
+%<latexrelease>\cs_set_eq:NN \everypar \tex_everypar:D
+%<latexrelease>
%<latexrelease>\EndModuleRelease
\ExplSyntaxOff
%</2ekernel|latexrelease>
@@ -1220,4 +1282,3 @@
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-
diff --git a/Master/texmf-dist/source/latex/base/ltplain.dtx b/Master/texmf-dist/source/latex/base/ltplain.dtx
index e0fbcecf1b6..5fa70396794 100644
--- a/Master/texmf-dist/source/latex/base/ltplain.dtx
+++ b/Master/texmf-dist/source/latex/base/ltplain.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltplain.dtx}
- [2021/04/18 v2.3f LaTeX Kernel (Plain TeX)]
+ [2021/07/16 v2.3g LaTeX Kernel (Plain TeX)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltplain.dtx}
@@ -906,6 +906,7 @@
\finalhyphendemerits=5000
\adjdemerits=10000
% \end{macrocode}
+% \begin{macrocode}
% \looseness=0, cleared by TeX after each paragraph
% \pausing=0
% \holdinginserts=0
@@ -915,9 +916,24 @@
% \tracingparagraphs=0
% \tracingpages=0
% \tracingoutput=0
+% \end{macrocode}
+% In the past \LaTeX{} used the default value of \texttt{1} for
+% \cs{tracinglostchars} because this was the best it could do. This
+% way one would at least get a warning in the \texttt{.log}
+% file. e-\TeX{} improved on that and supported a value of \texttt{2}
+% to show the warning on the terminal, so we could have changed the
+% default when we made the e-\TeX{} extensions required---however,
+% we overlooked that oportunity.
+% In 2021 this parameter was improved on again and now also accepts
+% the value \texttt{3}
+% (error on the terminal). This made us realize that we should
+% change the default. Using \texttt{3} would really be the
+% best, but for compatibility reasons we only use \texttt{2}.
+% \changes{v2.3g}{2021/07/16}{Use 2 as default value for \cs{tracinglostchars}}
% \begin{macrocode}
-\tracinglostchars=1
+\tracinglostchars=2
% \end{macrocode}
+% \begin{macrocode}
% \tracingcommands=0
% \tracingrestores=0
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltsect.dtx b/Master/texmf-dist/source/latex/base/ltsect.dtx
index 29ea142ba6c..67974c73874 100644
--- a/Master/texmf-dist/source/latex/base/ltsect.dtx
+++ b/Master/texmf-dist/source/latex/base/ltsect.dtx
@@ -31,7 +31,7 @@
%%% From File: ltsect.dtx
%<*driver>
% \fi
-\ProvidesFile{ltsect.dtx}[2020/12/05 v1.1e LaTeX Kernel (Sectioning)]
+\ProvidesFile{ltsect.dtx}[2021/07/28 v1.1f LaTeX Kernel (Sectioning)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltsect.dtx}
@@ -765,7 +765,7 @@
% The |\addcontentsline{|\meta{table}|}{|\meta{type}|}{|%
% \meta{entry}|}| command allows the user to add
% his/her own entry to a table of contents, etc. The command adds the
-% entry |\contentsline{|\meta{type}|}{|\meta{entry}|}{|\meta{page}|}|
+% entry |\contentsline{|\meta{type}|}{|\meta{entry}|}{|\meta{page}|}{}|
% to the |.|\meta{table} file.
%
% This macro is implemented as an application of |\addtocontents|.
@@ -833,7 +833,7 @@
% \end{macro}
%
% \begin{macro}{\contentsline}
-% The |\contentsline{|\meta{type}|}{|\meta{entry}|}{|\meta{page}|}|
+% The |\contentsline{|\meta{type}|}{|\meta{entry}|}{|\meta{page}|}{}|
% macro produces a \meta{type} entry in a table of contents, etc.
% It will appear in the |.toc| or other file. For example,
% The entry for subsection 1.4.3 in the table of contents for
@@ -848,10 +848,44 @@
% without expanding them.
%
% \begin{macrocode}
-\def\contentsline#1{\csname l@#1\endcsname}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/11/15}%
+%<latexrelease> {\contentsline}{Four arguments}%
+% \end{macrocode}
+%
+% In the toc file \cs{contentsline} is followed by 4 arguments
+% these days, but only the first 3 are used in the old
+% interface. The fourth was by default empty and only used when
+% \pkg{hyperref} was loaded. We now pick up all 4 arguments, save
+% the last one away in \cs{@contentsline@destination} and then call
+% the old interface. This is done to simplify the interface to
+% \pkg{hyperref} and to prepare for future changes.
+% \changes{v1.1f}{2021/07/28}{Pick up four arguments (gh/633)}
+% \begin{macrocode}
+\def\contentsline#1#2#3#4{\gdef\@contentsline@destination{#4}%
+ \csname l@#1\endcsname{#2}{#3}}
+% \end{macrocode}
+% Default definition.
+% \begin{macrocode}
+\let\@contentsline@destination\@empty
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\contentsline}{Four arguments}%
+%<latexrelease>
+%<latexrelease>\def\contentsline#1{\csname l@#1\endcsname}
+%<latexrelease>\let\@contentsline@destination\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
+%
+%
% |\@dottedtocline{|\meta{level}|}{|\meta{indent}|}{|\meta{numwidth}%
% |}{|\meta{title}|}{|\meta{page}|}|:
% Macro to produce a table of contents line with the following
diff --git a/Master/texmf-dist/source/latex/base/ltshipout.dtx b/Master/texmf-dist/source/latex/base/ltshipout.dtx
index f773cd23da2..7f6555d18cf 100644
--- a/Master/texmf-dist/source/latex/base/ltshipout.dtx
+++ b/Master/texmf-dist/source/latex/base/ltshipout.dtx
@@ -32,8 +32,8 @@
%%% From File: ltshipout.dtx
%
% \begin{macrocode}
-\providecommand\ltshipoutversion{v1.0i}
-\providecommand\ltshipoutdate{2021/03/17}
+\providecommand\ltshipoutversion{v1.0j}
+\providecommand\ltshipoutdate{2021/06/09}
% \end{macrocode}
%
%<*driver>
@@ -283,7 +283,7 @@
% includes the background and foreground material).
%
% \textbf{Note:} Just like \hook{shipout/before} this hook is
-% not meant to be used for adding adding typeset material back
+% not meant to be used for adding typeset material back
% to the main vertical list---it might vanish or the
% vertical spacing will be wrong!
%
@@ -867,7 +867,7 @@
% \begin{macrocode}
\cs_new:Npn \@@_execute_main_cont:Nnnn #1#2#3#4 {
\box_if_empty:NTF #1
- { \@latex@warning{Ignoring~ void~ shipout~ box} }
+ { \@latex@warning@no@line{ Ignoring~ void~ shipout~ box } }
{
% \end{macrocode}
% Otherwise we assume that we will ship something and prepare for
@@ -935,9 +935,8 @@
% practice way is to use the request mechanism.
% \begin{macrocode}
{ \box_if_empty:NTF #1
- { \@latex@warning{
- Shipout~ box~ was~ voided~ by~ hook,\MessageBreak
- ignoring~ shipout~ box }
+ { \@latex@warning@no@line { Ignoring~ void~ shipout~ box.
+ \MessageBreak The~ shipout~ box~ was~ voided~ by~ hook~ code }
}
% \end{macrocode}
% Finally, if the box is still non-empty we are nearly ready to
@@ -1183,9 +1182,8 @@
% \begin{macrocode}
\cs_gset_eq:NN \@@_run_firstpage_hook: \prg_do_nothing:
\cs_gset:Npn \@@_add_firstpage_material:Nn ##1 ##2 {
- \@latex@warning{
- First~ page~ is~ already~ shipped~ out,~ ignoring\MessageBreak
- \string##1 }
+ \@latex@warning{ First~ page~ is~ already~ shipped~ out,~ ignoring
+ \MessageBreak \string##1 }
}
}
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltvers.dtx b/Master/texmf-dist/source/latex/base/ltvers.dtx
index c8c3e618a55..9ce8d74cce3 100644
--- a/Master/texmf-dist/source/latex/base/ltvers.dtx
+++ b/Master/texmf-dist/source/latex/base/ltvers.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltvers.dtx}
- [2021/04/16 v1.1g LaTeX Kernel (Version Info)]
+ [2021/08/10 v1.1h LaTeX Kernel (Version Info)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltvers.dtx}
@@ -112,10 +112,10 @@
%</2ekernel>
%<latexrelease>\edef\latexreleaseversion
%<*2ekernel|latexrelease>
- {2021-06-01}
+ {2021-11-15}
%</2ekernel|latexrelease>
%<*2ekernel>
-\def\patch@level{1}
+\def\patch@level{0}
% \end{macrocode}
%
% \begin{macro}{\development@branch@name}
@@ -230,6 +230,7 @@
% \changes{v1.0o}{2015/01/19}{Optional argument}
% \changes{v1.0q}{2015/02/19}{Swap argument order}
% \changes{v1.1f}{2021/03/18}{Add support for usage in \cs{NewModuleRelease}}
+% \changes{v1.1h}{2021/08/10}{Add error to aid debugging}
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
@@ -257,6 +258,15 @@
{\@IncludeInRelease{#1}[#1]}}}
\def\finish@module@release#1#2#3{%
\toks@{[#1] #3}%
+ \begingroup
+ \edef\x{\detokenize\expandafter{\new@modulename}}%
+ \edef\y{\detokenize{#2}}%
+ \expandafter\endgroup
+ \ifx\x\y \else
+ \@latex@error{\noexpand\IncludeInRelease dated #1 in a module is not
+ allowed.\MessageBreak Use a date at least equal to \new@moduledate
+ \space for complete rollback}\@ehd
+ \fi
\ifnum\expandafter\@parse@version\new@moduledate//00\@nil
>\expandafter\@parse@version\fmtversion//00\@nil
\GenericInfo{}{Applying: \the\toks@}%
diff --git a/Master/texmf-dist/source/latex/base/makeindx.dtx b/Master/texmf-dist/source/latex/base/makeindx.dtx
index e8e48e60b06..9dc03a8431e 100644
--- a/Master/texmf-dist/source/latex/base/makeindx.dtx
+++ b/Master/texmf-dist/source/latex/base/makeindx.dtx
@@ -121,7 +121,7 @@
% \begin{macrocode}
%<makeidx>\ProvidesPackage{makeidx}
%<showidx>\ProvidesPackage{showidx}
- [2014/09/29 v1.0m Standard LaTeX package]
+ [2021/10/04 v1.0m Standard LaTeX package]
% \end{macrocode}
%
% \subsection{Makeidx}
@@ -261,7 +261,7 @@
%
% \begin{macro}{\raggedbottom}
% \begin{macro}{\flushbottom}
-% The definition of these macros from \texttt{latex.dtx} is changed
+% The definitions of these macros from the \LaTeX{} format are changed
% here to add the execution of |\@mkidx| to |\@texttop|, which is
% executed at the top of each page.
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/preload.dtx b/Master/texmf-dist/source/latex/base/preload.dtx
index b2ca24bce5b..bf2bfebbfa9 100644
--- a/Master/texmf-dist/source/latex/base/preload.dtx
+++ b/Master/texmf-dist/source/latex/base/preload.dtx
@@ -45,7 +45,7 @@
%<+tex> \ProvidesFile{preload.ltx}
% \fi
% \ProvidesFile{preload.dtx}
- [2014/09/29 v2.1g LaTeX Kernel (Font Preloading)]
+ [2021/10/04 v2.1g LaTeX Kernel (Font Preloading)]
%
%
%
@@ -179,7 +179,7 @@
% We begin by loading the math extension font (cmex10)
% and the \LaTeX{} line and circle fonts.
% It is necessary to do this explicitly since these are
-% used by \texttt{lplain.tex} and \texttt{latex.tex}.
+% used by the \LaTeX{} format.
% Since the internal font name contains |/| characters
% and digits we construct the name via |\csname|.
% These are the only fonts (!) that must be loaded in this file.
diff --git a/Master/texmf-dist/source/latex/base/slides.dtx b/Master/texmf-dist/source/latex/base/slides.dtx
index 883e7d34f04..e63c1901d6d 100644
--- a/Master/texmf-dist/source/latex/base/slides.dtx
+++ b/Master/texmf-dist/source/latex/base/slides.dtx
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{slides.drv}
%</driver>
- [2020/11/23 v2.4b
+ [2021/10/04 v2.4b
%<+class> Standard LaTeX document class]
%<+cmd> SLiTeX definitions]
% \end{macrocode}
@@ -1342,7 +1342,7 @@
%
% \begin{environment}{description}
% The description environment is defined here -- while the itemize
-% and enumerate environments are defined in \file{latex.dtx}.
+% and enumerate environments are defined in the \LaTeX{} format.
%
% \begin{macrocode}
\newenvironment{description}{\list{}{\labelwidth\z@
@@ -1373,7 +1373,7 @@
% \begin{macro}{\theenumii}
% \begin{macro}{\theenumiii}
% \begin{macro}{\theenumiv}
-% The counters are already defined in \file{latex.dtx}, but their
+% The counters are already defined in the \LaTeX{} format, but their
% representation is changed here.
%
% \begin{macrocode}
@@ -2349,7 +2349,7 @@ COLOR LAYER\\[.75in]%
%
% \changes{v2.2j}{1994/03/11}{Corrected \cs{@oval}, like previous
% \changes{v2.4a}{2016/03/29}{Initialize in \cs{@oval}tests added for
-% latex/4452} change to \file{latex.dtx}.}
+% latex/4452} change to the \LaTeX{} format.}
% \begin{macrocode}
\def\line(#1,#2)#3{\if@visible\@xarg #1\relax \@yarg #2\relax
\@linelen #3\unitlength
diff --git a/Master/texmf-dist/source/latex/base/tulm.fdd b/Master/texmf-dist/source/latex/base/tulm.fdd
index 5c1566a5bad..243cbe30cc7 100644
--- a/Master/texmf-dist/source/latex/base/tulm.fdd
+++ b/Master/texmf-dist/source/latex/base/tulm.fdd
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright 2016-2019
+% Copyright 2016-2021
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
@@ -30,7 +30,7 @@
%\iffalse This is a META comment
%
% File `cmfonts.fdd'.
-% Copyright (C) 2016-2019 LaTeX Project
+% Copyright (C) 2016-2021 LaTeX Project
%
%
%<TUlmr>\ProvidesFile{tulmr.fd}
@@ -42,7 +42,7 @@
%<*driver>
\ProvidesFile{tulm.drv}
%</driver>
- [2017/01/26 v1.8 Standard LaTeX font definitions for Latin Modern]
+ [2021/07/23 v1.8a Standard LaTeX font definitions for Latin Modern]
%
%<*driver>
\documentclass{ltxdoc}
@@ -63,6 +63,7 @@
%\fi
%
% \section{TUlmr}
+% \changes{v1.8a}{2021/07/23}{Use OpenType font for TU/lmr/m/ui}
% \begin{macrocode}
%<*TUlmr>
\DeclareFontFamily{TU}{lmr}{}
@@ -93,7 +94,7 @@
\DeclareFontShape{TU}{lmr}{m}{sc}%
{<-> \UnicodeFontFile{lmromancaps10-regular}{\UnicodeFontTeXLigatures}}{}
\DeclareFontShape{TU}{lmr}{m}{ui}%
- {<-> ec-lmu10}{}
+ {<-> \UnicodeFontFile{lmromanunsl10-regular}{\UnicodeFontTeXLigatures}}{}
\DeclareFontShape{TU}{lmr}{m}{scsl}%
{<-> \UnicodeFontFile{lmromancaps10-oblique}{\UnicodeFontTeXLigatures}}{}
\DeclareFontShape{TU}{lmr}{b}{n}
diff --git a/Master/texmf-dist/source/latex/base/utf8ienc.dtx b/Master/texmf-dist/source/latex/base/utf8ienc.dtx
index 79c725915c7..75990d1b036 100644
--- a/Master/texmf-dist/source/latex/base/utf8ienc.dtx
+++ b/Master/texmf-dist/source/latex/base/utf8ienc.dtx
@@ -216,7 +216,7 @@
%<+ts1> \ProvidesFile{ts1enc.dfu}
%<+x2> \ProvidesFile{x2enc.dfu}
%<+all> \ProvidesFile{utf8enc.dfu}
-%<-utf8-2018> [2021/01/27 v1.2l UTF-8 support for inputenc]
+%<-utf8-2018> [2021/06/21 v1.2n UTF-8 support]
% \end{macrocode}
%
% \begin{macrocode}
@@ -443,14 +443,16 @@
% \changes{v1.1g}{2005/09/27}{Real spaces do not show up so use \cs{space}}
% \changes{v1.1o}{2015/08/28}{Show Unicode number of character in hex}
% \changes{v1.2a}{2018/03/24}{Error message improved for non-UTF-8 sequences}%
+% \changes{v1.2m}{2021/06/08}{Normalize various error messages as kernel errors}
% \begin{macrocode}
\UTFviii@undefined@err{#1}%
% \end{macrocode}
%
% \begin{macrocode}
\else
- \PackageError{inputenc}{Invalid UTF-8 byte sequence}%
- \UTFviii@invalid@help
+ \@latex@error{Invalid UTF-8 byte sequence (\expandafter
+ \@gobblefour\string#1)}%
+ \UTFviii@invalid@help
\fi
% \end{macrocode}
%
@@ -468,8 +470,8 @@
% \changes{v1.2f}{2018/10/05}{Show invalid byte in hex}%
% \begin{macrocode}
\def\UTFviii@invalid@err#1{%
- \PackageError{inputenc}{Invalid UTF-8 byte "\UTFviii@hexnumber{`#1}}%
- \UTFviii@invalid@help}
+ \@latex@error{Invalid UTF-8 byte "\UTFviii@hexnumber{`#1}}%
+ \UTFviii@invalid@help}
% \end{macrocode}
%
% \begin{macrocode}
@@ -487,7 +489,7 @@
% \changes{v1.2a}{2018/03/24}{Macro added}%
% \begin{macrocode}
\def\UTFviii@undefined@err#1{%
- \PackageError{inputenc}{Unicode character \expandafter
+ \@latex@error{Unicode character \expandafter
\UTFviii@splitcsname\string#1\relax
\MessageBreak
not set up for use with LaTeX}%
@@ -776,8 +778,7 @@
\ifnum\catcode\count@=13
\uccode`\~=\count@\uppercase{\def\UTFviii@tmp{\@empty\@empty~}}%
\else
- \PackageError{inputenc}%
- {Cannot define non-active Unicode char value < 00A0}%
+ \@latex@error{Cannot define non-active Unicode char value < 00A0}%
\@eha
\def\UTFviii@tmp{\UTFviii@tmp}%
\fi
@@ -803,7 +804,7 @@
% past this error.
% \begin{macrocode}
\ifnum\count@>"10FFFF\relax
- \PackageError{inputenc}%
+ \@latex@error
{\UTFviii@hexnumber\count@\space too large for Unicode}%
{Values between 0 and 10FFFF are permitted}%
\fi
@@ -1703,17 +1704,31 @@
%<all,t1>\DeclareUnicodeCharacter{1E03}{\.b}
% \end{macrocode}
% \changes{v1.2k}{2021/01/27}{Added various additional dot accents (gh/484)}
+% \changes{v1.2n}{2021/06/21}{more extended latin entries for gh/593}
% \begin{macrocode}
%<all,t1>\DeclareUnicodeCharacter{1E0D}{\d d}
+%<all,t1>\DeclareUnicodeCharacter{1E1E}{\.F}
+%<all,t1>\DeclareUnicodeCharacter{1E1F}{\.f}
%<all,t1>\DeclareUnicodeCharacter{1E25}{\d h}
+%<all,t1>\DeclareUnicodeCharacter{1E30}{\@tabacckludge'K}
+%<all,t1>\DeclareUnicodeCharacter{1E31}{\@tabacckludge'k}
%<all,t1>\DeclareUnicodeCharacter{1E37}{\d l}
+%<all,t1>\DeclareUnicodeCharacter{1E8E}{\.Y}
+%<all,t1>\DeclareUnicodeCharacter{1E8F}{\.y}
%<all,t1>\DeclareUnicodeCharacter{1E43}{\d m}
%<all,t1>\DeclareUnicodeCharacter{1E45}{\.n}
%<all,t1>\DeclareUnicodeCharacter{1E47}{\d n}
%<all,t1>\DeclareUnicodeCharacter{1E5B}{\d r}
%<all,t1>\DeclareUnicodeCharacter{1E63}{\d s}
%<all,t1>\DeclareUnicodeCharacter{1E6D}{\d t}
+%<all,t1>\DeclareUnicodeCharacter{1E90}{\^Z}
+%<all,t1>\DeclareUnicodeCharacter{1E91}{\^z}
%<all,t1>\DeclareUnicodeCharacter{1E9E}{\SS}
+%<all,t1>\DeclareUnicodeCharacter{1EF2}{\@tabacckludge`Y}
+%<all,t1>\DeclareUnicodeCharacter{1EF3}{\@tabacckludge`y}
+% \end{macrocode}
+%
+% \begin{macrocode}
%<all,x2,t2c,t2b,t2a,t1,utf8>\DeclareUnicodeCharacter{200C}{\textcompwordmark}
% \end{macrocode}
% \changes{v1.1s}{2016/02/28}{Add more hyphens and dashes}
@@ -2083,8 +2098,7 @@
\ifnum\catcode\count@=13
\uccode`\~=\count@\uppercase{\def\UTFviii@tmp{\@empty\@empty~}}%
\else
- \PackageError{inputenc}%
- {Cannot define non-active Unicode char value < 00A0}%
+ \PackageError{inputenc}{Cannot define non-active Unicode char value < 00A0}%
\@eha
\def\UTFviii@tmp{\UTFviii@tmp}%
\fi