latex3 / latex2e

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

More flexibility for `\RemoveFromHook` in one-time hooks #1514

Closed gusbrs closed 3 weeks ago

gusbrs commented 4 weeks ago

Brief outline of the enhancement

I'm considering an use case, from the perspective of a package I maintain, in which I'm attempting to use package lthooks to add support/compatibility code for other packages, and I'd like to suggest it would be possible and desirable to offer more flexibility in the ability to remove code chunks from package hooks.

Concretely, the idea I'm entertaining is whether users could disable compatibility code added by my package by using \RemoveFromHook. And I'm finding out it is harder than it needs to be. Let's say package postnotes adds some support code for amsmath using the package/amsmath/after hook (as indeed it does). If amsmath is loaded before postnotes it does not seem possible to remove the chunk at all. Calling \RemoveFromHook{package/amsmath/after}[postnotes] either before amsmath or between the two packages results in warning Cannot remove chunk 'postnotes' from hook 'package/amsmath/after' because the hook does not exist. (of course, after both packages it is too late). If postnotes is loaded before amsmath, the attempt to remove the chunk succeds, as long as it is done between the two packages. If done before them we also get the warning of non existing hook.

However, as far as I can see, being this a one-time package hook, with any load order of the packages, and any placement of \RemoveFromHook{package/amsmath/after}[postnotes] which is not after both packages were loaded the instruction would be non-ambiguous. And could be honored. The suggestion is that it would.

Minimal example showing the current behaviour

Currently, this is the only ordering of things with which I could remove the chunk:

% \RequirePackage{latexbug} % sorry, MWE for motivation only...
\documentclass{article}

\usepackage{postnotes}

\RemoveFromHook{package/amsmath/after}[postnotes]

\usepackage{amsmath}

\begin{document}
Hello World.
\end{document}
FrankMittelbach commented 3 weeks ago

This is a deliberate restriction. \RemoveFromHook is intended for situations where you own the hook chunk and have full control over its use. It is not meant to be used on hook chunks from other package as it is a destructive operation and one package should not overwrite another package's chunk in a destructive way.

The documentation says:

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

So to solve your use case use something like

\documentclass{article}

\usepackage{postnotes}

\ShowHook{package/amsmath/after}

%prevent postnotes from being applied non-destructive:
\AddToHook{package/amsmath/after}[insteadofpostnotes]{\typeout{--your code or just empty--}}
\DeclareHookRule{package/amsmath/after}{insteadofpostnotes}{voids}{postnotes}

\ShowHook{package/amsmath/after}

\usepackage{amsmath}

% proof that postnotes hook chunk was not applied
\ShowHook{postnotes/note/begin}

\begin{document}
Hello World.
\end{document}
gusbrs commented 3 weeks ago

@FrankMittelbach , thanks for considering and explaining.

Indeed I hadn't thought of the destructive aspect of \RemoveFromHook. For the problem I had in mind, it didn't matter, but in general, I can only concur. It makes sense.

And I was unaware of voids, and how to use it for this case. Thanks for that too.

FrankMittelbach commented 3 weeks ago

And I was unaware of voids, and how to use it for this case. Thanks for that too.

RTFM :-) but rest assured, I had to reread the manual as well, before I hit on the fact that we considered (and for a change) documented it. This morning we thought, yes, looks like something is missing here.

gusbrs commented 3 weeks ago

RTFM :-)

Ouch! :-)

FrankMittelbach commented 3 weeks ago

Who needs to read documentation when everything is so intuitive :-)