1

I'm maintaining a document class which loads the bidi package. bidi is very picky about loading order, and must be loaded after: float, graphics, ntheorem and a bunch of others. The thing is, my document class doesn't need all of these packages itself, while documents using the class may well need them.

This puts me in a dilemma: Do I add \RequirePackage commands for what needs to come before bidi, known I'm creating all sorts of false dependencies? Or, alternatively, do I keep things as they are and break compatibility of my class with, well, almost everything?

I tried using something like \AtBeginDocument, but that didn't seem to work - I still get the same errors as I do what loading bidi early, e.g.:

(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty)

! LaTeX Error: Unable to properly define \@@leqno; primitive \leqno no longer p
rimitive.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.2564 \@saveprimitive\leqno\@@leqno
  • It's probably enough to explain this in the package documentation and tell them to load your package last. – Andrew Sep 19 '17 at 18:13
  • Related: Test if a package (or package option) is loaded – Werner Sep 19 '17 at 18:17
  • @Andrew: It's another thing people have to do in order to use the document class. Some will do it, some won't... which is why it's important for me to do it for them. – einpoklum Sep 19 '17 at 22:46
7

Usually it's OK to do

\AtBeginDocument{\usepackage{bidi}}

but if for some reason that doesn't work for you an alternative would be to just document to your users that they should load the package in the right sequence with other packages and add a test

\AtBeginDocument{\@ifpackageloaded{bidi}{}{\ClassError{zzz}{I told you to load bidi}{}}

to check that it is loaded in the preamble.

  • Using this answer I got a lead for my own answer. – einpoklum Sep 19 '17 at 23:10
2

Sit tight and at the end of this answer all will be resolved and packages will be loaded in just the order they like.


Phase 1: From bidi deferral to polyglossia deferral

You are likely failing to defer the loading of bidi because bidi is automatically loaded by polyglossia when you indicate you'll be using a right-to-left language (specifically, Hebrew) - at the point of that indication, probably; and early-on, certainly.

So let's drop the explicit loading of bidi, and defer polyglossia:

\AtBeginDocument{\usepackage{polyglossia}}

... but this also results in an error, e.g.

! Undefined control sequence.
<recently read> \setmainlanguage 

l.125 \setmainlanguage
                      {english}

Phase 2: Deferring polyglossia-related commands

While you want to defer loading polyglossia, your preamble likely has any polyglossia-related command, such as \setmainlanguage, \setotherlanguage, \newfontfamily and so on.

Ok, then - let's defer all of them together! After all, we're not actually typesetting any text in any language while still in the preamble. Sample code:

\AtBeginDocument{
 \usepackage{polyglossia}
 \setmainlanguage{english}
 \setotherlanguage[numerals=arabic,calendar=gregorian]{hebrew}
 \newfontfamily\hebrewfont[Script=Hebrew]{David CLM}
}

... but we're foiled again. This time the with the error:

! LaTeX Error: Can be used only in preamble.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.21 \AtEndPreamble
                   {\let\bbl@set@language\xpg@set@language} %for biblatex

Phase 3: Tweaking the deferral destination does the trick

Now this is interesting... it looks like one of the polyglossia-related commands issues an \AtEndPreamble, which can obviously not be issued when the document has begun and the preamble is ended. But if that's when it really wants to run, why not oblige it? Let's defer polyglossia (and thus also bidi) to \AtEndPreamble instead of to \AtBeginDocument:

\RequirePackage{etoolbox} % provides \AtEndPreamble
\AtEndPreamble{
 \usepackage{polyglossia}
 \setmainlanguage{english}
 \setotherlanguage[numerals=arabic,calendar=gregorian]{hebrew}
 \newfontfamily\hebrewfont[Script=Hebrew]{David CLM}
}

... and this works.

Phase 4: Tuning the deferral

@UlrikeFischer suggests we can make do with just preventing polyglossia from loading bidi early on. Thus, the following:

\RequirePackage{etoolbox} % provides \AtEndPreamble
\RequirePackage{polyglossia} 
\setmainlanguage{english}
\AtEndPreamble{
 \setotherlanguage[numerals=arabic,calendar=gregorian]{hebrew}
 \newfontfamily\hebrewfont[Script=Hebrew]{David CLM}
}

Also works. Now other packages which expect polyglossia to be available will not be adversely affected.


Note: The polyglossia-related commands can use \AtEndPremable because polyglossia itself makes it available by its own \RequirePackage{etoolbox}; but I'm not making that assumption in the code above.

  • @DavidCarlisle: Yeah. Will edit accordingly, thanks. – einpoklum Sep 19 '17 at 23:19
  • Since you provided no minimal example and none of the information needed to guess any of this, you guarantee that you'll be the only one who can possibly answer your question. Anybody else reading your answer will wonder how it relates to the question, given that it makes an enormous number of assumptions for which there is no evidence at all. Why do you think the OP is using Hebrew? Or has \setmainlanguage in the preamble (or even has a preamble)? Obviously, you think this because you're the OP, but that doesn't make it answer the question asked. – cfr Sep 20 '17 at 0:08
  • It is probably enough to defer the \setotherlanguage. – Ulrike Fischer Sep 20 '17 at 8:21
  • @UlrikeFischer: Possibly, but I'm not sure there's anything to be gained by this "half-deferral". – einpoklum Sep 20 '17 at 8:29
  • There are quite a number of packages which try to guess the language of the document. If this is set to late you can get problems too. Also you are not the first to discover \AtEndPreamble. If everyone moves everything there you gain nothing. So use it with care. – Ulrike Fischer Sep 20 '17 at 8:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.