Es handelt sich um eine Folgefrage zu dieser Frage.

Eine eigene Dokumentenklasse (Oberklasse) definiert – neben anderem, was hier unwichtig ist – eine bestimmte Darstellung der Seitenzahl im Fuß. Dabei wird auf die Nummer der letzten Seite zugegriffen, wie in der Antwort auf die vorausgehende Frage vorgeschlagen.

Eine Unterklasse soll – wiederum neben diversen anderen Definitionen, die hier ausgelassen sind – nun zusätzlich dafür sorgen, dass eine Aufzählung mit \begin{document} und \end{document} automatisch begonnen und beendet wird.

Das Problem dabei ist, dass die Unterklasse plötzlich nicht mehr auf das Label LastPage zugreifen kann, was mit der Oberklasse allein noch funktioniert hat: LaTeX Warning: Reference LastPage on page 1 undefined on input line 6.

Öffne in Overleaf
\begin{filecontents}{meine-oberklasse.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{meine-oberklasse}

\LoadClass{article}

\RequirePackage{scrlayer-scrpage}

\AtBeginDocument{\textbf{Anfangstext der Oberklasse}\par}
\BeforeClosingMainAux{\addtocounter{page}{-1}\label{LastPage}}
\cfoot{Seite \pagemark{} von \pageref{LastPage}}
\end{filecontents}
\begin{filecontents}{meine-unterklasse.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{meine-unterklasse}

\LoadClass{meine-oberklasse}

\AtBeginDocument{Es folgt eine Aufzählung.\begin{itemize}}
\AtEndDocument{\end{itemize}Die Aufzählung ist beendet.}
\end{filecontents}
\documentclass{meine-unterklasse}
\usepackage{blindtext}

\begin{document}
\item \blindtext
\end{document}

gefragt 24 Mär '19, 00:14

Cletus's gravatar image

Cletus
1.6k45566
Akzeptiert-Rate: 75%

1

Soweit ich das sehen kann, ist das Verhalten nicht den zwei Klassen anzulasten, sondern liegt darin begründet, dass durch \begin{itemize}...\end{itemize} in \AtBeginDocument/\AtEndDocument eine implizite Gruppe erstellt wird, die die Anwendung von \BeforeClosingMainAux unterdrückt (das liegt an der Implementation des Befehls). Das grundsätzliche Problem lässt sich auch in https://gist.github.com/moewew/3133afd014037a87099be17b0be98928 reproduzieren (dort lässt es sich eventuell durch Herumschieben der Gruppe beheben, bei Deiner Anwendung ist das wohl nicht ganz so einfach).

(24 Mär '19, 09:10) moewe
1

Es ist keine gute Idee, eine Gruppe um alles zu packen (\begin{document}/\end{document} vermeidet das bewusst), verwende \itemize / \enditemize.

(24 Mär '19, 11:29) Ulrike Fischer

Das Problem ist, dass Du in zweifacher Weise gegen die Regeln für \AtBeginDocument verstoßen hast. Zum einen heißt es in »LaTeX2e for class and package writers« schon seit Ende 1996 explizit:

However, note that code in the \AtBeginDocument hook is part of the preamble. Thus there are restrictions on what can be put there; in particular, no typesetting can be done.

und

The \AtBeginDocument hook should not be used for code that does any typesetting since the typeset result would be unpredictable.

Auf Deutsch sagt beides, dass man \AtBeginDocument keinesfalls dazu verwenden sollte, Code auszuführen, der bereits Satzaufgaben ausführt. Dazu gehören nicht nur unmittelbare Ausgaben, sondern eben auch der Anfangscode von Umgebungen, die bereits Formatierungen für den nachfolgenden Text durchführen.

Zum anderen ist es ein (mehr oder weniger) ungeschriebenes Gesetz, dass man niemals das gesamte Dokument per \AtBeginDocument und \AtEndDocument in eine Gruppe packen sollte. \begin{document} und \end{document} sind bewusst keine normale Umgebungen, die eine Gruppe implizieren, sondern verhindern explizit, dass sie eine Gruppe bilden. Zerbricht man das, kann alles mögliche schief gehen.

Behebt man in deinem Beispiel wenigst das letzte Problem:

Öffne in Overleaf
\begin{filecontents}{meine-oberklasse.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{meine-oberklasse}

\LoadClass{article}

\RequirePackage{scrlayer-scrpage}

\AtBeginDocument{\textbf{Anfangstext der Oberklasse}\par}
\BeforeClosingMainAux{\addtocounter{page}{-1}\label{LastPage}}
\cfoot{Seite \pagemark{} von \pageref{LastPage}}
\end{filecontents}
\begin{filecontents}{meine-unterklasse.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{meine-unterklasse}

\LoadClass{meine-oberklasse}

\AtBeginDocument{Es folgt eine Aufzählung.\itemize}
\AtEndDocument{\enditemize Die Aufzählung ist beendet.}
\end{filecontents}
\documentclass{meine-unterklasse}
\usepackage{blindtext}

\begin{document}
\item \blindtext
\end{document}

so funktioniert das Beispiel zwar, es ist aber noch immer ein Verstoß gegen die explizit dokumentierte Verwendung von \AtBeginDocument. Ich würde also unbedingt davon abraten, das so zu machen.

Übrigens stellt das Paket etoolbox einen Befehl \AfterEndPreamble bereit, der Code bereits als Teil des Dokumentkörpers ausführt. Allerdings ist auch damit nicht ratsam eine Gruppe zu beginnen, die man erst bei \AtEndDocument beendet. Auch das geht schief. Auch hier kommt das Ende der Gruppe schlicht zu spät. Auch hier wird ein Teil des Codes von \end{document} noch innerhalb der Gruppe von \begin{itemize}…\end{itemize} ausgeführt, was unbedingt zu vermeiden ist.

Was dagegen funktionieren würde:

Öffne in Overleaf
\begin{filecontents}{meine-oberklasse.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{meine-oberklasse}

\LoadClass{article}

\RequirePackage{scrlayer-scrpage}
\RequirePackage{etoolbox}

\AfterEndPreamble{\textbf{Anfangstext der Oberklasse}\par}
\BeforeClosingMainAux{\addtocounter{page}{-1}\label{LastPage}}
\cfoot{Seite \pagemark{} von \pageref{LastPage}}
\end{filecontents}
\begin{filecontents}{meine-unterklasse.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{meine-unterklasse}

\LoadClass{meine-oberklasse}

\AfterEndPreamble{Es folgt eine Aufzählung.\begin{itemize}}
\pretocmd{\enddocument}{\end{itemize}Die Aufzählung ist beendet.}{}{}
\end{filecontents}
\documentclass{meine-unterklasse}
\usepackage{blindtext}

\begin{document}
\item \blindtext
\end{document}

Hier wird die itemize-Umgebung beendet, noch bevor irgendwelcher Code von \end{document} ausgeführt wird. Aber auch hier betrachte ich es als durchaus nicht ideal, dass das gesamte Dokument in einer Gruppe steckt. Außerdem kann auch das schief gehen, wenn jemand anderer auf dieselbe Idee kommt und ebenfalls Code durch \pretocmd{\enddocument}{…}{…}{…} ausführen lässt. Das kommt dann sehr auf den jeweiligen Code an.

Permanenter link

beantwortet 24 Mär '19, 11:40

gast3's gravatar image

gast3
(ausgesetzt)
Akzeptiert-Rate: 53%

bearbeitet 24 Mär '19, 11:43

Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×32
×17
×13

gestellte Frage: 24 Mär '19, 00:14

Frage wurde gesehen: 3,696 Mal

zuletzt geändert: 24 Mär '19, 11:43