2

The standalone package, with its subpreambles option, gives error if the xy package is loaded in one of the standalone input files. This is shown by the following M(n)WE:

\begin{filecontents}{testxy}
\documentclass{article}
\usepackage{xy}
\begin{document}
Foo.
\end{document}
\end{filecontents}
%
\documentclass{article}
\usepackage[subpreambles]{standalone}
\begin{document}
\input{testxy}
\end{document}

the compilation of which failing with the error (two compilations needed):

! Undefined control sequence.
l.58 \xylet
           @\xy@begindvi=\literal@
?

Do you see what's going on?

Denis Bitouzé
  • 9,652
  • 4
  • 27
  • 85

1 Answers1

2

The error happens at line 58 of xyidioms.tex; let's look at it

 43 \ifx\AtEndDocument\undefined
 44  \expandafter\ifx\csname amsppt.sty\endcsname\relax
 45  \let\xysetup@@=\xysetup@dummy
 46  \else
 47  \def\xysetup@@#1{%
 48  \expandafter\def\expandafter\topmatter\expandafter{\topmatter
 49  #1\xyuncatcodes}}\fi
 50 \else
 51  \def\xysetup@@#1{\AtBeginDocument{#1\xyuncatcodes}}
 52 \fi
 53 \ifx\xysetup@@\xysetup@dummy\else
 54  \xysetup@@{\let\xysetup@@=\xysetup@dummy \xyuncatcodes}\fi
 55 \xywarnifdefined\xyclosedown@@
 56 \ifx\AtEndDocument\undefined \let\xyclosedown@@=\eat@
 57 \else \def\xyclosedown@@#1{\AtEndDocument{#1}}\fi
 58 \xylet@\xy@begindvi=\literal@

The conditional at line 43 returns false, so

\def\xysetup@@#1{\AtBeginDocument{#1\xyuncatcodes}}

is performed. Since now \xysetu@@ is not the same as \xysetup@dummy,

\xysetup@@{\let\xysetup@@=\xysetup@dummy \xyuncatcodes}

is executed. Unfortunately, inside \standalonepreambles, the macro \AtBeginDocument is redefined to immediately deliver its argument, as this interactive run shows

(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyidioms.tex
! Undefined control sequence.
l.58 \xylet
           @\xy@begindvi=\literal@
? i\show\AtBeginDocument
> \AtBeginDocument=\long macro:
#1->#1.
<insert>   \show\AtBeginDocument

l.58 \xylet
           @\xy@begindvi=\literal@
? 

This means that the \xysetup@@ command makes TeX into executing \xyuncatcodes at the spot. This performs, among other things, \makeatother. So now @ is not a letter any more.

Line 55 prints two @ characters, but we're already after \begin{document}, so there's nothing wrong. The following conditional returns false and defines \xyclosedown rather than \xyclosedown@@ but this raises no error. Now line 58 has the tokens

\xylet•@•\xy•@•b•e•g•i•n•d•v•i•=•\literal•@

( is used to separate the tokens). Since \xylet is not defined, the error is raised.

Conclusion: it can't work. Any package that performs category code changes of @ at \AtBeginDocument will fail similarly.

egreg
  • 1,121,712
  • As usually with egreg's answers, I was confidently reading the clever explanations and, suddenly, I came across "it can't work". Then, all things considered, argh! Isn't it possible to patch xy to make it work? – Denis Bitouzé Apr 08 '16 at 18:14
  • 1
    @DenisBitouzé No, sorry. This happens when xy is being loaded. Call it in the main document and forget about subpreambles. – egreg Apr 08 '16 at 19:29
  • OK. Is there a way to know what are the packages that perform category code changes of @ at \AtBeginDocument? – Denis Bitouzé Apr 08 '16 at 21:15
  • @DenisBitouzé There are more than 3000 packages. – egreg Apr 08 '16 at 21:19
  • Hence my question: if there would be a simple test that lets me know what are the packages that perform category code changes of @ at \AtBeginDocument, I could track them down with a simple bash script (okay, as a test, I could just use something similar to what I exposed in my question but if there would be something more direct, it would be nice). – Denis Bitouzé Apr 08 '16 at 21:41