hyperref icon indicating copy to clipboard operation
hyperref copied to clipboard

Use of \Hy@org@chapter doesn't match its definition.

Open dbitouze opened this issue 3 years ago • 13 comments

The following MCE used to work with previous versions of hyperref:

\documentclass{book}
\usepackage{xpatch}
\usepackage{hyperref}
\makeatletter
\xapptocmd{\@chapter}{%
  \addtocontents{foo}{\protect\addvspace{10\p@}}%
}{}{}
\makeatother
\begin{document}
\chapter{Foo}
\end{document}

but now it gives the following error:

! Use of \Hy@org@chapter doesn't match its definition.
\@chapter ...@next \Hy@org@chapter \addtocontents 
                                                  {foo}{\protect \addvspace ...

l.42 \chapter{Foo}
                
?

Sorry I didn't notice the first hyperref's version where the problem arose.

BTW, the issue is similar with \AddToHook{cmd/@chapter/before}{...} instead of \xapptocmd{\@chapter}{...}{}{}.

dbitouze avatar Jun 09 '22 20:06 dbitouze

Sorry no, that never worked. Not with hyperref. I get the same error with e.g. texlive 2018. Perhaps you made the patch before hyperref was loaded, then it can work, as LaTeX grabs the arguments.

u-fischer avatar Jun 09 '22 20:06 u-fischer

Sorry for the irrelevant MCE above. Here is a relevant one, which used to work with an up to date TL 2021, but which doesn't work with an up to date TL 2022 (but, because of nameref, I guess used to work with version v7.00n of hyperref):

\documentclass{book}
\usepackage{xpatch}
\usepackage{hyperref}
\usepackage{nameref}
\makeatletter
\xapptocmd{\@chapter}{%
  \addtocontents{foo}{\protect\addvspace{10\p@}}%
}{}{}
\makeatother
\begin{document}
\chapter{Foo}
\end{document}

dbitouze avatar Jun 10 '22 15:06 dbitouze

yes, hyperref no longer loads nameref in begindocument but directly. This means that now first nameref patches \@chapter and then hyperref, where previously it was the other way round.

I don't think that your patch is good as it breaks so easily if packages are loaded in a different order. Why do you patch \@chapter so late?

u-fischer avatar Jun 10 '22 15:06 u-fischer

Why do you patch \@chapter so late?

Because it is done in a package of mine used with a class of mine which loads hyperref. And because this class also provides several configurations regarding cleveref (which has to be loaded after hyperref), I can't in this class rely on \AddToHook{begindocument/before}{\RequirePackage{hyperref}}.

My attempts with hooks sadly fail:

\documentclass{book}
\AddToHook{begindocument/before}{\RequirePackage{hyperref}}
\AddToHook{package/hyperref/before}
{%
  \AddToHook{cmd/@chapter/before}{%
    \addtocontents{foo}{\protect\addvspace{10\p@}}%
  }%
}
\begin{document}
\chapter{Foo}
\end{document}

dbitouze avatar Jun 10 '22 19:06 dbitouze

if this is for a class then why don't you patch \@chapter directly after if has been defined (probably you load book or something like that?). And why do you use \xapptocmd above instead of prepending the code? Why not

\AddToHook{cmd/@chapter/before}{%
  \addtocontents{foo}{\protect\addvspace{10\p@}}%
}{}{}

u-fischer avatar Jun 10 '22 19:06 u-fischer

if this is for a class then why don't you patch \@chapter directly after if has been defined (probably you load book or something like that?).

Hmmm, quite intricate, sorry... For the documentations of each of my classes, I make use of the corresponding classes. And there are some (common) tools and settings that:

  • I need for these documentations,
  • I don't need (and don't want at first glance) for the classes themselves,

and that, therefore, I gathered in a package. To be more explicit, these tools are tcolorbox “theorems“ (in fact, e.g., warnings named dbwarning), the lists of which not providing by default extra vertical spaces between “theorems“ belonging to different chapters (hence, e.g. \AddToHook{cmd/@chapter/before}{\addtocontents{dbwarninglist}{\protect\addvspace{10\p@}}}.

And why do you use \xapptocmd above instead of prepending the code? Why not

\AddToHook{cmd/@chapter/before}{%
  \addtocontents{foo}{\protect\addvspace{10\p@}}%
}{}{}

Isn't it what I tried in https://github.com/latex3/hyperref/issues/244#issuecomment-1152651271?

dbitouze avatar Jun 10 '22 19:06 dbitouze

And why do you use \xapptocmd above instead of prepending the code?

Ah, do you mean: why \xapptocmd instead of \xpretocmd? To be honest, I don't remember right now...

dbitouze avatar Jun 10 '22 19:06 dbitouze

My attempts with hooks sadly fail:

I think you are overdoing with the hooks, it should be enough to patch the command. But it fails only because you forgot the \makeatletter

u-fischer avatar Jun 10 '22 20:06 u-fischer

I think you are overdoing with the hooks, it should be enough to patch the command. But it fails only because you forgot the \makeatletter

Indeed it works with \AddToHook{cmd/@chapter/before}{ but hasn't any effect. With \AddToHook{cmd/@chapter/after}{, it fails with the same kind of error:

\documentclass{book}
\RequirePackage{hyperref}
\makeatletter
\AddToHook{cmd/@chapter/after}{%
  \addtocontents{foo}{\protect\addvspace{10\p@}}%
}%
\makeatother
\begin{document}
\chapter{Foo}
\end{document}

gives:

! Use of \Hy@org@chapter doesn't match its definition.
\@chapter ...fi \Hy@next \Hy@org@chapter \UseHook 
                                                  {cmd/@chapter/after}
l.9 \chapter{Foo}
               
?

dbitouze avatar Jun 10 '22 20:06 dbitouze

What do you mean with it has not effect? If I use an existing list, like e.g. lof it works fine for me. And no, you can not append to \@chapter, not after hyperref has been loaded. It doesn't matter if you append with \xapptocmd, the after hook, or something else. Prepending code to a command works in many case, appending is typically much more dangerous as quite often the command is still looking for arguments. See Commands that look ahead in the ltcmdhooks documentation.

u-fischer avatar Jun 10 '22 20:06 u-fischer

What do you mean with it has not effect? If I use an existing list, like e.g. lof it works fine for me.

That's because it is provided by default for the figures. But that's not the case for the lists of tcolorbox “theorems“:

\documentclass{book}
\usepackage{xpatch}
\usepackage{tcolorbox}
% \usepackage{hyperref}

\tcbuselibrary{theorems}

\newtcbtheorem[list inside=dbwarninglist,number within=chapter]{dbwarning}{Warning}%
{}{dbwa}

% \makeatletter
% \xapptocmd{\@chapter}{%
%   \addtocontents{dbwarninglist}{\protect\addvspace{10\p@}}%
% }{}{}
% \makeatother

\begin{document}
\chapter{One}
\begin{dbwarning}{Warning One One}{}
\end{dbwarning}
\begin{dbwarning}{Warning One Two}{}
\end{dbwarning}
%
\begin{figure}
  \caption{Figure One One}
\end{figure}
\begin{figure}
  \caption{Figure One Two}
\end{figure}
\chapter{Two}
\begin{dbwarning}{Warning Two One}{}
\end{dbwarning}
\begin{dbwarning}{Warning Two Two}{}
\end{dbwarning}
%
\begin{figure}
  \caption{Figure Two One}
\end{figure}
\begin{figure}
  \caption{Figure Two Two}
\end{figure}
%
\listoffigures
\tcblistof[\chapter*]{dbwarninglist}{Table of warnings}
\end{document}

And no, you can not append to \@chapter, not after hyperref has been loaded. It doesn't matter if you append with \xapptocmd, the after hook, or something else. Prepending code to a command works in many case, appending is typically much more dangerous as quite often the command is still looking for arguments. See Commands that look ahead in the ltcmdhooks documentation.

Too bad: it used to work with older versions of hyperref.

dbitouze avatar Jun 11 '22 07:06 dbitouze

What do you mean with it has not effect? If I use an existing list, like e.g. lof it works fine for me.

That's because it is provided by default for the figures. But that's not the case for the lists of tcolorbox “theorems“:

Well sure, I used lof for the test because it is already there. But if I add to your example

\makeatletter
\AddToHook{cmd/@chapter/before}{%
  \addtocontents{dbwarninglist}{\protect\addvspace{10\p@}}%
}{}{}
\makeatother

I get

image

So where is your problem?

Too bad: it used to work with older versions of hyperref.

Yes, but as soon as any package (or a user) had loaded nameref earlier it would have broken too. So it was very fragile. If you want to patch \@chapter with \xapptocmd then do it early. Your package is probably loaded before hyperref, so do the patch directly. Don't delay it behind hyperref.

Btw: the newest hyperref allows to suppress the sectioning patches. See section 4.4 "Patches and how to suppress them" in the documentation. I actually hope that classes take this over and add the needed targets themselves so that those patches can be removed from hyperref.

u-fischer avatar Jun 11 '22 08:06 u-fischer

[...]

So where is your problem?

I'm confused: that works perfectly. Sorry for the noise!

Too bad: it used to work with older versions of hyperref.

Yes, but as soon as any package (or a user) had loaded nameref earlier it would have broken too. So it was very fragile. If you want to patch \@chapter with \xapptocmd then do it early. Your package is probably loaded before hyperref, so do the patch directly. Don't delay it behind hyperref.

Okay.

Btw: the newest hyperref allows to suppress the sectioning patches. See section 4.4 "Patches and how to suppress them" in the documentation. I actually hope that classes take this over and add the needed targets themselves so that those patches can be removed from hyperref.

I'm sorry, but I'm not sure to understand: in the present case, what am I supposed to do?

BTW, the first sentence of this section starts with “The patches to external commands made by hyperref can be avoided in toto”: “toto”?

dbitouze avatar Jun 13 '22 07:06 dbitouze