Почему \AtEndDocument не выполняется в *конце* документа?

Почему \AtEndDocument не выполняется в *конце* документа?

Я, должно быть, делаю что-то невероятно глупое, но я свел это к минимуму, насколько это возможно, но безуспешно. Я работаю над ошибкой, которая возникла в недавнем коммите вpagectrl @ca7dc3.

У меня есть следующий минимальный пример:

\documentclass{minimal}

\AtEndDocument{\typeout{wat}}

\begin{document}
hello, world
\end{document}

со следующим журналом

This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdflatex 2014.12.7)  9 DEC 2014 22:03
entering extended mode
 restricted \write18 enabled.
 %&-line parsing enabled.
**\input success-6.tex
(./success-6.tex (/usr/local/texlive/2014/texmf-dist/tex/latex/base/minimal.cls
Document Class: minimal 2001/05/25 Standard LaTeX minimal class
)
No file success-6.aux.
\openout1 = `success-6.aux'.

LaTeX Font Info:    Checking defaults for OML/cmm/m/it on input line 5.
LaTeX Font Info:    ... okay on input line 5.
LaTeX Font Info:    Checking defaults for T1/cmr/m/n on input line 5.
LaTeX Font Info:    ... okay on input line 5.
LaTeX Font Info:    Checking defaults for OT1/cmr/m/n on input line 5.
LaTeX Font Info:    ... okay on input line 5.
LaTeX Font Info:    Checking defaults for OMS/cmsy/m/n on input line 5.
LaTeX Font Info:    ... okay on input line 5.
LaTeX Font Info:    Checking defaults for OMX/cmex/m/n on input line 5.
LaTeX Font Info:    ... okay on input line 5.
LaTeX Font Info:    Checking defaults for U/cmr/m/n on input line 5.
LaTeX Font Info:    ... okay on input line 5.
wat
[1{/usr/local/texlive/2014/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
(./success-6.aux) ) 
Here is how much of TeX's memory you used:
 17 strings out of 493109
 369 string characters out of 6135004
 52967 words of memory out of 5000000
 3574 multiletter control sequences out of 15000+600000
 3640 words of font info for 14 fonts, out of 8000000 for 9000
 1141 hyphenation exceptions out of 8191
 14i,4n,10p,120b,92s stack positions out of 5000i,500n,10000p,200000b,80000s
</usr/local/texlive/2014/texmf-dist/fonts/type1/public/amsfo
nts/cm/cmr10.pfb>
Output written on success-6.pdf (1 page, 11394 bytes).
PDF statistics:
 12 PDF objects out of 1000 (max. 8388607)
 7 compressed objects within 1 object stream
 0 named destinations out of 1000 (max. 500000)
 1 words of extra memory for PDF output out of 10000 (max. 10000000)

Что меня особенно огорчает, так это эта часть файла журнала:

wat
[1{/usr/local/texlive/2014/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]

Я интерпретирую это так, что watэто печатается еще до начала документа ( [). Что я делаю не так?

решение1

Крючок \AtEndDocumentв основном использовался для печати материалов в конце документа, например адресов или заметок.

Пакет atveryendпредоставляет еще два хука с говорящими названиями:

\documentclass{minimal}
\usepackage{atveryend}

\AtEndDocument{\typeout{atend}}
\AfterLastShipout{\typeout{afterlastshipout}}
\AtVeryEndDocument{\typeout{atveryend}}

\begin{document}
hello, world
\end{document}

Вот вывод на терминале:

This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./veryend.tex
LaTeX2e <2014/05/01>
Babel <3.9l> and hyphenation patterns for 79 languages loaded.
(/usr/local/texlive/2014/texmf-dist/tex/latex/base/minimal.cls
Document Class: minimal 2001/05/25 Standard LaTeX minimal class
) (/usr/local/texlive/2014/texmf-dist/tex/latex/oberdiek/atveryend.sty)
(./veryend.aux)
atend
[1{/usr/local/texlive/2014/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
afterlastshipout
(./veryend.aux)
atveryend
 )</usr/local/texlive/2014/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on veryend.pdf (1 page, 11397 bytes).
Transcript written on veryend.log.

Обратите внимание, что atveryendнапечатанопослефайл .auxбыл прочитан.

решение2

\AtEndDocumentобновления \@enddocumenthookв \enddocumentмакросе. Ниже показано его расположение в \enddocument(отlatex.ltx):

\def\enddocument{%
   \let\AtEndDocument\@firstofone
   \@enddocumenthook% <---- Hook for \AtEndDocument
   \@checkend{document}%
   \clearpage% <---- Starts the final page builder
   \begingroup
     \if@filesw
       \immediate\closeout\@mainaux
       \let\@setckpt\@gobbletwo
       \let\@newl@bel\@testdef
       \@tempswafalse
       \makeatletter \@@input\jobname.aux
     \fi
     \@dofilelist
     \ifdim \font@submax >\fontsubfuzz\relax
       \@font@warning{Size substitutions with differences\MessageBreak
                  up to \font@submax\space have occurred.\@gobbletwo}%
     \fi
     \@defaultsubs
     \@refundefined
     \if@filesw
       \ifx \@multiplelabels \relax
         \if@tempswa
           \@latex@warning@no@line{Label(s) may have changed.
               Rerun to get cross-references right}%
         \fi
       \else
         \@multiplelabels
       \fi
     \fi
   \endgroup
   \deadcycles\z@\@@end}

Обратите внимание, что \@enddocumenthookвыполняетсядо \clearpage, который запускает конструктор страниц. Таким образом, watвыводитсядоначинается построение страницы. Чтобы она вывелапосле, вы \clearpageможете исправить\enddocument или следовать некоторым рекомендациям вМогу ли я подключиться к концу документа, нопосле?\clearpage):

\documentclass{article}
\usepackage{etoolbox}
\patchcmd{\enddocument}% <cmd>
  {\clearpage}% <search>
  {\clearpage\typeout{wat}}% <replace>
  {}{}% <success><failure>
\begin{document}
hello, world
\end{document}

Отчеты .log:

[1{/usr/local/texlive/2014/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
wat

решение3

Вы можете разместить свои макросы в конце документа после \clearpageбез использования пакета \patchcmdfrom etoolbox. Первый метод можно использовать в очень простых случаях:

\AtEndDocument{\clearpage\typeout{wat}}

Это работает, потому что второй \clearpage(из внутренних компонентов LaTeX) обрабатывается, когда основной вертикальный список включает только отбрасываемые элементы, т. е. пустая страница не создается. Но этот метод может не сработать, когда другие пакеты используют \AtEndDocumentи предполагают, что их макросы будут обработаны до \clearpage. Тогда вы можете использовать более надежный метод. Определите \afterclearpageмакрос, который сдвигает свой аргумент после внутренней \clearpageуправляющей последовательности:

\documentclass{article}
\def\afterclearpage#1#2\clearpage{#2\clearpage#1}
\AtEndDocument{\afterclearpage{\typeout{wat}}}

\begin{document}
hello, world
\end{document}

Связанный контент