6

Why doesn't \IfPackageLoadedT allow empty lines inside its argument?

Suppose I have:

\documentclass{article} \IfPackageLoadedT{amsmath}{ \newcommand{\foo}{} } \begin{document} a \end{document} 

This throws the error (line 6 being the empty line):

Runaway argument? { \newcommand {\foo }{} ./test.tex:6: Paragraph ended before \IfPackageLoadedT was complete. <to be read again> \par l.6 

However, after removing the empty line, the document compiles as usual. Note that this doesn't happen with the variants \IfPackageLoadedTF and \IfPackageLoadedF.

3
  • we should probably fix that Commented May 17 at 6:41
  • 1
    the default for any \def is not to allow blank lines, you need \long\def to allow this, but looks like we missed some cases. Commented May 17 at 6:45
  • 2
    github.com/latex3/latex2e/issues/1733 Commented May 18 at 10:13

2 Answers 2

3

This has been fixed in the sources for the June 2025 LaTeX release.

Old:

\def\IfPackageLoadedT #1#2{\IfPackageLoadedTF{#1}{#2}{}} 

New:

\def\IfPackageLoadedT #1{\IfPackageLoadedTF{#1}\@firstofone\@gobble} 

the new version avoids reading the code argument with the macro defined via \def which is not \long. The code argument is read with \@firstofone or @gobble depending on the result of the test. The argument taking the package name is still read with a non-\long macro, so blank lines (or missing }) for that argument are flagged.

Several other \If....T macros are similarly adjusted.

https://github.com/latex3/latex2e/commit/8dcd37fa5d84bc95efcdedf7919ac7febbac44d7

2
  • Why these commands are defined with \def instead of \NewDocumentCommand which allows to set individually whether arguments are long or not? (I means something like\NewDocumentCommand{\IfPackageLoadedT}{ m +m }.) Commented May 18 at 19:32
  • 2
    @jlab most of the core latex.ltx uses lower level commands partly for historic reasons with slower machines, partly as you have to start somewhere: you can't make all of latex.ltx be read after NewDocumentCommand is defined and for changes like this, just to preserve the style of that section of code (although we did consider using NewDocumentCommand here). Commented May 18 at 20:04
3

The reason is that the \IfPackageLoaded macro in latex.ltx is defined by

\def\IfPackageLoadedT #1#2{\IfPackageLoadedTF{#1}{#2}{}} 

Note that it is defined by \def, not by \long\def. The \def TeX primitive declares macros. If these declared macros have parameters and \long prefix isn't used then these parameters are not allowed to include \par token. The \par token is typically generated at each empty line by TeX token processor.

The reason of this behavior is: if a user forgets to insert a closing object of the parameter (i.e. the } in this case), the problem is revealed at the first following empty line, not at the end of file. It means the problem is revealed relatively early.

Because the parameter of \IfPackageLoadedT can include a TeX code which manipulates with \par tokens, then the \long prefix is better in this case.

1
  • 2
    or even better arrange the first argument is non long but the second is, eg \def\IfPackageLoadedT #1{\IfPackageLoadedTF{#1}\@firstofone\@gobble} Commented May 18 at 10:06

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.