phst / lualatex-math

LuaTeX-specific enhancements and fixes for LaTeX math typesetting
LaTeX Project Public License v1.3c
12 stars 3 forks source link

Loading error `Illegal parameter number` if amsmath is not loaded yet #26

Open muzimuzhi opened 9 months ago

muzimuzhi commented 9 months ago

(first reported in https://github.com/latex3/mathtools/issues/55#issuecomment-1717077850)

Loading lualatex-math before amsmath throws error

! Illegal parameter number in definition of \__hook package/amsmath/after.
% !TeX program = lualatex
\documentclass{article}
\usepackage{lualatex-math}

\begin{document}
content
\end{document}

The problem is caused by two LuaTeX primitive \alignmark used in

\__lltxmath_after_package_or_now:nn { amsmath } {
  ...
  \@ifpackagelater { amsmath } { 2020/09/23 } { } {
    \__lltxmath_patch:NNnnn \subarray \cs_set:Npn { #1 } {
      ...
      $ \m@th \scriptstyle ## $
      \hfil
      \crcr
    } {
      ...
      \Ustartmath
      \m@th
      \scriptstyle
      \alignmark \alignmark
      \Ustopmath
      \hfil
      \crcr
    }
    ...
  }
}

https://github.com/phst/lualatex-math/blob/c4c7e6323923970e52754da00d04cf0983f67b7c/lualatex-math.dtx#L564

Replacing \alignmark \alignmark with ## seems to solve the problem. I'm guessing that's because \alignmark is not doubled by hook macros.

What surprised me is, using \alignmark in \AddToHook directly in preamble won't throw such an error.

% !TeX program = lualatex
\begin{filecontents}[force]{x-math.sty}
\AddToHook{package/amsmath/after}{%
  \def\y{\alignmark\alignmark}%
}
\end{filecontents}

\documentclass{article}
\AddToHook{package/amsmath/after}{%
  \def\x{\alignmark\alignmark}%
}

\input x-math.sty % errors

\usepackage{x-math} % errors

\begin{document}
content
\end{document}
muzimuzhi commented 9 months ago

Note the current test suite throws such error too. After running l3build check,

$ grep -rn 'Illegal parameter number in definition' build/test/**/*.log
build/test/amsmath.log:130:! Illegal parameter number in definition of \__hook package/amsmath/after.
build/test/deprecation.log:96:! Illegal parameter number in definition of \__hook package/amsmath/after.
build/test/icomma.log:66:! Illegal parameter number in definition of \__hook package/amsmath/after.
build/test/kernel-style.log:64:! Illegal parameter number in definition of \__hook package/amsmath/after.
muzimuzhi commented 9 months ago

What surprised me is, using \alignmark in \AddToHook directly in preamble won't throw such an error.

Nope. The condition to reproduce the problem is to add to a hook which already contains \alignmark\alignmark, rather than ##.

\documentclass{article}

\AddToHook{package/amsmath/after}{%
%   \def\x{##}% works
  \def\x{\alignmark\alignmark}% doesn't work
}

\AddToHook{package/amsmath/after}{}

\begin{document}
\end{document}

Now this looks like a hooks management issue.


Update: According to the LuaTeX Reference Manual (April 2023, v1.16), sec. 2.8.5 "\alignmark and \aligntab"

The primitive \alignmark duplicates the functionality of # inside alignment preambles, ...

Thus my simplified examples are not typical usages, but should still work.

muzimuzhi commented 9 months ago

It seems in LuaTeX, when appeared in replacement text of a macro, number of consecutive \alignmarks is halved, just like number of #s. For example, \def\x{\alignmark\alignmark} defines \x holding a single \alignmark.

Since the code of a hook is stored in a macro, number of \alignmarks is halved when first added to a hook, then halved twice when later some code is added to the same hook again.