latex3 / latex2e

The LaTeX2e kernel
https://www.latex-project.org/
LaTeX Project Public License v1.3c
1.82k stars 251 forks source link

Provide a handier command than `\DeclareHookRule` #1355

Closed dbitouze closed 1 month ago

dbitouze commented 1 month ago

Brief outline of the enhancement

Provide a more convenient command than \DeclareHookRule to specify the order relationship between multiple labels for a given hook. Indeed, in the case of several rules for the same hook that have to be executed in a given order, it is currently a pain:

A handier command than \DeclareHookRule{⟨hook⟩}{⟨label1⟩}{⟨relation⟩}{⟨label2⟩} could be:

\HandierDeclareHookRule{⟨hook⟩}{⟨order relation⟩}{⟨label1⟩,⟨label2⟩,...}

I admit that this may only make sense for a ⟨relation⟩ which is an order relation.

Minimal example showing the current behaviour

\RequirePackage{latexbug}       % <--should be always the first line (see CONTRIBUTING)!
\begin{filecontents*}[overwrite]{myclass.cls}
\ProvidesExplClass
  {myclass}
  {2024-05-23}
  {0.1}
  {
    My~Nice~Class.
  }
\NeedsTeXFormat{LaTeX2e}
\LoadClass { article }

\AddToHook{cmd/enddocument/before} [./D] {D}
\AddToHook{cmd/enddocument/before} [./C] {C}
\AddToHook{cmd/enddocument/before} [./B] {B}
\AddToHook{cmd/enddocument/before} [./A] {A}

% Order specification is a real pain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\DeclareHookRule{cmd/enddocument/before} {./A}{<}{./B}
\DeclareHookRule{cmd/enddocument/before} {./B}{<}{./C}
\DeclareHookRule{cmd/enddocument/before} {./C}{<}{./D}

% Changing the order is a real pain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \DeclareHookRule{cmd/enddocument/before} {./B}{<}{./D}
% \DeclareHookRule{cmd/enddocument/before} {./D}{<}{./A}
% \DeclareHookRule{cmd/enddocument/before} {./A}{<}{./C}
\end{filecontents*}

\documentclass{myclass}
\begin{document}
\end{document}

Minimal example showing the desired new behaviour

\RequirePackage{latexbug}       % <--should be always the first line (see CONTRIBUTING)!
\RequirePackage{latexbug}       % <--should be always the first line (see CONTRIBUTING)!
\begin{filecontents*}[overwrite]{myclass.cls}
\ProvidesExplClass
  {myclass}
  {2024-05-23}
  {0.1}
  {
    My~Nice~Class.
  }
\NeedsTeXFormat{LaTeX2e}
\LoadClass { article }

\AddToHook{cmd/enddocument/before} [./D] {D}
\AddToHook{cmd/enddocument/before} [./C] {C}
\AddToHook{cmd/enddocument/before} [./B] {B}
\AddToHook{cmd/enddocument/before} [./A] {A}

% Order specification is not a pain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\HandierDeclareHookRule{cmd/enddocument/before}{<}{./{A,B,C,D}}

% Changing the order is not a pain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \HandierDeclareHookRule{cmd/enddocument/before}{<}{./{B,D,A,C}}
\end{filecontents*}

\documentclass{myclass}
\begin{document}
\end{document}
u-fischer commented 1 month ago

hm, I'm wondering what you are doing that you need so many rules. Why don't you do \AddToHook{cmd/enddocument/before}{BDAC} directly?

dbitouze commented 1 month ago

Because the different codes are in my real case scattered throughout the source file of my class.

u-fischer commented 1 month ago

I suspect that you are misusing hooks. The hook rules are mostly meant for users and other package authors. If you think that they should be able to reorder your chunks or remove some of then, then put your code in such chunks, if you are the only one who wants to order, then put the code in commands like \mychunkA, \mychunkB and then put them inside the hook.

Also why are you using the cmd/enddocument/before hook instead of the enddocument hook? The generic cmd hooks are useful, but they basically patch commands, and so can more easily fail with catcode problems, see e.g. https://github.com/latex3/latex2e/issues/1099.

FrankMittelbach commented 1 month ago

I was about to ask for your real use case, but by now you have answered that. Hook rules are not meant to order code within a single package, that is as Ulrike mentioned rather a misuse of the hook machinery. The main point about hooks is that different packages can write to it and normally the order should be irrelevant. The rules are then available for the less common case that some order between different packages is needed, but that should be only occasionally needed and adds a time penalty if used unnecessarily. Within a single package or class order the code to write to a single hook appropriately and then no rules are necessary (or use docstrip to order it for you when the .cls is written).

I think that falls under "not planned".

dbitouze commented 1 month ago

OK, thanks.

@u-fischer

Also why are you using the cmd/enddocument/before hook instead of the enddocument hook?

The later doesn't work with the underlying class (standalone).