5

At the end of 2020, LaTeX added support for a general hook management system. The system allows me to execute \maketitle at the beginning of a document if I am in the preamble, or immediately if I am in the document:

\AddToHook{begindocument/end}{\maketitle}

LaTeX hooks are only available in TeX Live 2021 and later. However, I need my code to work at least in unupdated TeX Live 2020 (to support Overleaf) and ideally in TeX Live ≥ 2018. Pragmatically, I could rewrite my code as follows:

\ifx\@onlypreamble\@notprerr
  % We are in the document
  \maketitle
\else
  % We are in the preamble
  \RequirePackage{etoolbox}
  \AfterEndPreamble{\maketitle}
\fi

However, I would like to gradually convert my code to use LaTeX hooks and using compatibility code will only accumulate technical debt, which I would like to avoid.

Does there exist a polyfill package that adds (limited) support for LaTeX hooks and that would allow me to use LaTeX hooks in historical TeX Live versions? Like this:

\RequirePackage{lthooks-polyfill}
\AddToHook{begindocument/end}{\maketitle}

If not, what is the suggested migration path from code that does not use hooks to code that uses hooks and stays compatible with historical releases of TeX Live?

Witiko
  • 1,216
  • 1
    You could use etoolbox and \AfterEndPreamble, with a new latex this is an alias to the new hook, but it works also in older systems. – Ulrike Fischer Sep 11 '21 at 10:52
  • 3
    or you could take latexrelease.sty from the current release and roll your format forwards adding all new features, not just the hooks – David Carlisle Sep 11 '21 at 10:54
  • @DavidCarlisle That sounds interesting, thank you. However, since my code will be part of a package, I would prefer out-of-box compatibility with older versions of LaTeX. – Witiko Sep 11 '21 at 11:23
  • 4
    Do what Ulrike says then:-) – David Carlisle Sep 11 '21 at 11:27
  • @UlrikeFischer: I am looking at the code of etoolbox and I am not convinced that \AfterEndPreamble does the same thing before and after LaTeX 2020-10-01. Before LaTeX 2020-10-01, using \AfterEndPreamble after the end of the preamble issues an error (\protected\def\AfterEndPreamble{\@notprerr\@gobble}). After 2020-10-01, \AfterEndPreamble expands to \AddToHook{begindocument/end}, which behaves differently: "[...] after it is executed, all further attempts to add code to it will execute such code immediately". – Witiko Sep 11 '21 at 11:35
  • I recognize that this distinction is not important if the behavior of \AfterEndPreamble after the preamble is undefined by etoolbox, but it is important in my use case. Specifically, in order to use \AfterEndPreamble, I would need it to behave the same way as \AddToHook{begindocument/end} before LaTeX 2020-10-01. – Witiko Sep 11 '21 at 11:36
  • 1
    Well you will have to live with such differences. You can't expect that new code simply reproduces old code, then there would have been no need for the new code. If you want to use something that doesn't work in an older latex you will have to check the latex version and write compability code. – Ulrike Fischer Sep 11 '21 at 11:40
  • Perhaps. But it also means that using \AfterEndPreamble is not an answer to the question as stated. Thank you for the heads-up, but I am hoping that there exists a polyfill that would allow me to not pollute the package with compatibility code. – Witiko Sep 11 '21 at 11:41
  • 2
    @Witiko you can still use that hook to do the delay but just wrap it in something like \ifx\@nodocument\relax \maketitle\else \AfterEndPreamble{\maketitle}\fi that will work with old and new formats (needing etoolbox) – David Carlisle Sep 11 '21 at 11:47
  • @UlrikeFischer: But your point about the subtle difference between \AtBeginDocument and \AfterEndPreamble is well-taken. I have updated the original question. – Witiko Sep 11 '21 at 11:49
  • I added a last paragraph to the original question, so that it can be meaningfully answered with something other than "No, there does not exist such a polyfill." – Witiko Sep 12 '21 at 09:57

2 Answers2

4

Polyfills exist for features of the LaTeX kernel that came into existence by pulling a useful LaTeX package into the kernel. However, the concept of hooks is brand new and was inspired by a ragtag of different LaTeX packages: etoolbox, filehook, atbegshi, atveryend, and others.

As Ulrike points out in the comments below the original question, the \AfterEndPreamble command from the etoolbox package resembles the begindocument/end hook but only works in the preamble. Therefore, the answer seems to be a no: Although parts of the functionality of LaTeX hooks are available in different LaTeX packages, no comprehensive polyfill exists.

LaTeX hooks have been available since LaTeX 2020-10-01. Therefore, one migration path would be to write different code for LaTeX before and after 2020-10-01:

\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
\IfFormatAtLeastTF{2020-10-01}%
  {\AddToHook{begindocument/end}{\maketitle}}%
  {%
    \ifx\@onlypreamble\@notprerr
      % We are in the document
      \maketitle
    \else
      % We are in the preamble
      \RequirePackage{etoolbox}
      \AfterEndPreamble{\maketitle}
    \fi
  }

Alternatively, you can roll the LaTeX format forward by loading a current latexrelease.sty file, as noted by David in the comments below the original question and in Joseph's answer, or wait until you no longer need to support TeX Live < 2021.

Witiko
  • 1,216
  • Personally I would write your package stating it needs LaTeX 2020-10-01 and simply error if it's not available. You can then document that users can roll forward in their sources if necessary. – Joseph Wright Sep 13 '21 at 09:38
  • 1
    All else aside, \ifx\IfFormatAtLeastTF... \fi can be rewritten as \providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} – Phelype Oleinik Sep 13 '21 at 10:05
  • @JosephWright That is what we are going to do a couple years down the road, but as a matter of policy and practicality, I tend to keep my packages compatible with reasonably old LaTeX (4 to 5 years old), so that users that wish to use my package on Overleaf or Debian stable do not need to roll the LaTeX format forward. – Witiko Sep 13 '21 at 12:55
  • @PhelypeOleinik Thank you, I have updated the command. In the future, feel free to directly suggest changes by clicking the Improve this answer link. – Witiko Sep 13 '21 at 12:57
3

I would suggest setting a specification you require and then sticking to it: that has always been available in LaTeX using the optional argument to \NeedsTeXFormat, but today one would likely use a more controlled situation

\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
\IfFormatAtLeastTF{2020-10-01}%
  {}
  {%
    \PackageError{foo}
      {%
        This package requires LaTeX 2020-10-01 or newer!
      }
      \@ehc
    \endinput
  }

and then I would document that one can use latexrelease to obtain a sufficiently-new format on an older system.

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • Thank you, that is a useful suggestion, although it does not answer the question How can I use LaTeX hooks in historical versions of TeX Live? but rather How can I use LaTeX hooks and print a helpful error message in unsupported historical versions of TeX Live? – Witiko Sep 14 '21 at 09:37
  • @Witiko I hoped it did: you check, you issue an error, the user can then get the latest latexrelease and load if they cannot update their entire system. We are after all talking about someone who has downloaded your package. – Joseph Wright Sep 14 '21 at 10:35
  • Rolling the format forward is an extra step for the user, which requires that they have access to an up-to-date latexrelease.sty: an unrealistic expectation of many Overleaf users without their own TeX installations. Even if the user successfully rolls the format forward, this may adversely affect other packages written for older versions of LaTeX: Despite claims of backwards-compatibility, newer LaTeX formats reserve commands such as \localename that were previously free for grabs and change the behavior of established commands such as \usepackage. Therefore, I see it as a last resort. – Witiko Sep 14 '21 at 10:52
  • @Witiko On the need for latexrelease: we are talking about a new package which they must be uploading anyway. So it's just 'another file to add to a project' for a user. – Joseph Wright Sep 14 '21 at 11:09
  • @Witiko On the use of csnames, etc., well yes updates do mean names are added, that can't be avoided. But the same is true for any change, which again includes a package wanting a particular set of features. – Joseph Wright Sep 14 '21 at 11:10
  • I don't see latexrelease.sty readily available for download on the web. You can download .ins and .dtx files and interpret the former with TeX to produce latexrelease.sty. This requires a working installation of TeX. – Witiko Sep 14 '21 at 11:41
  • To your second point: Many newer features of LaTeX can be polyfilled using what is already available in the historical version of TeX Live without upgrading LaTeX: a potentially breaking change for many historical packages. This is more difficult for the programmer but also more convenient to the user. – Witiko Sep 14 '21 at 11:41