ich habe folgendes Problem:
Mir liegt eine Sammlung von Übungsaufgaben in einzelnen Dateien vor, aus
denen ich für das zu erzeugende Übungsblatt die passenden durch die
Angabe des Dateinamens auswähle, d.h. die document-Umgebung der
Hauptdatei besteht im Wesentlichen aus den Befehlen
\include{Blatt1}
\include{Blatt2}
etc. (unter Verwendung des passenden \includeonly-Befehls)
und die Dateien Blatt<Nr>.tex aus den Zeilen
\Aufgabe{Dateiname1}
\Aufgabe{Dateiname2}
etc.
In dem Befehl \Aufgabe werden i.W. das Argument an den \input-Befehl
weitergegeben und einige Formatierungsbefehle ausgeführt.
Nun benötige ich für die ein oder andere Aufgabe ein spezielles Paket,
z.B. pstricks. Ich möchte jetzt aber nicht in jeder ausgewählten
Aufgabendatei nachschauen, welches Paket ich dafür noch zusätzlich im
Hauptdokument laden muss. Das soll in der Aufgabendatei verankert sein
und beim LaTeX-Lauf berücksichtigt werden. Allerdings bin ich ja zu
diesem Zeitpunkt bereits aus der Präambel raus und kann nicht mehr
direkt mit \usepackage arbeiten.
Also habe ich mir den Befehl \Praeambel{arg} geschrieben, der sein
Argument arg (z.B. \usepackage{pstricks}) in eine externe Datei
rausschreibt. Beim nächsten LaTeX-Lauf wird diese Datei dann in der
Praeambel eingelesen. Problem ist natürlich dabei, dass im ersten Lauf
das Paket noch nicht geladen ist und deshalb die daraus genutzten
Befehle Fehlermeldungen werfen. Das ist sehr unschön, aber mit Hilfe des
Parameters -interaction=nonstopmode mit Bauchschmerzen zu ertragen. Ich
möchte aber lieber LaTeX ohne Bauchschmerzen nutzen...
Meine Überlegung ist nun, quasi zwei LaTeX-Läufe hintereinander
anzustoßen und beim ersten nur nach den \Praeambel-Befehlen zu suchen
und alles andere zu ignorieren. Aber ich habe keine Idee, wie ich
a) zwei LaTeX-Läufe hintereinander durch nur einen Aufruf ausführen kann
und
b) wie ich alles außer \Praeambel{...} ignorieren kann.
Gibt es schon fertige Lösungen/Lösungsansätze dazu, die ich einfach noch
nicht gefunden habe?
Oder behandelt man dieses Problem grundsätzlich anders?
Über Tipps, Hinweise, Schlagworte zum Suchen etc. bin ich dankbar!
Gruß, Claas
wirklich quick, wirklich dirty, wirklich unkomfortabel und
andere können es wahrscheinlich besser, aber vielleicht hilft
es ja:
--8<--- aufgaben-main.tex -------
\documentclass[a4paper,10pt]{scrartcl}
\usepackage[utf8x]{inputenc}
\catcode`\%=9
\input{aufgabe}
\catcode`\%=14
\begin{document}
Ein Test.
\input{aufgabe}
\end{document}
-->8-----------------------------
--8<--- aufgabe.tex -------------
%\catcode`\%=14\usepackage{graphicx}\catcode`\%=9
%\endinput
Wenn es klappt, bleibt die Fehlermeldung aus:
\scalebox{2}[1]{Extrabreit}
-->8-----------------------------
Gruß, Mike
Nur so am Rande: Wie löst du das Problem der Reihenfolge, in der
bestimmte Pakete gearde nicht geladen werden sollten.
Im Moment gar nicht, wobei aber eine gewisse "Grundausstattung" an
Paketen (inputenc, fontenc, babel, csquotes, hyperref,...) automatisch
geladen wird.
Dann würde ich dir empfehlen, deine Grundausstattung zu erweitern, in
ein stylefile zu packen und alle Aufgaben auf auf diese Pakete zu
beschränken. Das braucht Disziplin sorgt aber auch für Kohärenz bei
deiner Aufgabenkonstruktion. Ansonsten bekommst du schnell Probleme
mit Reihenfolgen z.B. Referenz, Tabellen usw und optionclash z.B.
xcolor, caption (mit oder ohne Option "table")
Klar, man will nicht zuviele Pakete laden, die sich womöglich noch
beißen, aber durch deinen Ansatz handelst du dir das alles und noch
mehr ein. Am Ende kannst du bestimmte Aufgaben nicht mehr kombinieren,
weil dein System dich dazu zwingt.. das ist nicht empfehlenswert
Claas Hemig schrieb:
> Mir liegt eine Sammlung von Übungsaufgaben in einzelnen Dateien vor,
[...]
> Nun benötige ich für die ein oder andere Aufgabe ein spezielles Paket,
> z.B. pstricks. Ich möchte jetzt aber nicht in jeder ausgewählten
> Aufgabendatei nachschauen, welches Paket ich dafür noch zusätzlich im
> Hauptdokument laden muss. Das soll in der Aufgabendatei verankert sein
> und beim LaTeX-Lauf berücksichtigt werden. Allerdings bin ich ja zu
> diesem Zeitpunkt bereits aus der Präambel raus und kann nicht mehr
> direkt mit \usepackage arbeiten.
>
> Also habe ich mir den Befehl \Praeambel{arg} geschrieben, der sein
> Argument arg (z.B. \usepackage{pstricks}) in eine externe Datei
> rausschreibt. Beim nächsten LaTeX-Lauf wird diese Datei dann in der
> Praeambel eingelesen. Problem ist natürlich dabei, dass im ersten Lauf
> das Paket noch nicht geladen ist und deshalb die daraus genutzten
> Befehle Fehlermeldungen werfen. Das ist sehr unschön, aber mit Hilfe des
> Parameters -interaction=nonstopmode mit Bauchschmerzen zu ertragen. Ich
> möchte aber lieber LaTeX ohne Bauchschmerzen nutzen...
>
> Meine Überlegung ist nun, quasi zwei LaTeX-Läufe hintereinander
> anzustoßen und beim ersten nur nach den \Praeambel-Befehlen zu suchen
> und alles andere zu ignorieren. Aber ich habe keine Idee, wie ich
> a) zwei LaTeX-Läufe hintereinander durch nur einen Aufruf ausführen kann
> und
> b) wie ich alles außer \Praeambel{...} ignorieren kann.
>
> Gibt es schon fertige Lösungen/Lösungsansätze dazu, die ich einfach noch
> nicht gefunden habe?
> Oder behandelt man dieses Problem grundsätzlich anders?
Vorschlag 1:
============
Ich würde dafür nicht Dokumente per \input zusammenstoppeln, sondern
mittels des docstrip-package.
Da kannst du in den einzelnen, die Aufgabensammlung ausmachenden
Dateien Tags setzen, um anzugeben, was in die Präambel muss und
was in den "body" der document-Umgebung und mittels \generate dann
die einzelnen Dazeien auslesen und beim Auslesen eine neue Datei/ein
neues Dokument zusammensetzen lassen, in der/dem das alles dann
hübsch sortiert auftaucht.
Wenn man von den folgenden vier Dateien die Datei main.tex entweder
mit TeX oder mit LaTeX compiliert, wird eine neue Datei erzeugt, mit
Namen "NeueAufgabenZusammenstellung.tex". Die wiederum stellt
den compilierbaren Quellcode für ein fertiges Dokument dar.
In diesem Quellcode ist Zeug, was in die Präambel gehört, in der
Präambel, und Zeug, was in den "body" der document-Umgebung
gehört, befindet sich im "body" der document-Umgebung.
"NeueAufgabenZusammenstellung.tex" läßt sich mit LaTeX compilieren
und man bekommt das neue Aufgabenblatt als dvi oder pdf:
Datei main.tex:
\input docstrip
\nopreamble
\nopostamble
\generate{%
\file{NeueAufgabenZusammenstellung.tex}{%
\from{frame.tex}{preamble}%
\from{Aufg1.tex}{preamble}%
\from{Aufg2.tex}{preamble}%
\from{frame.tex}{body}%
\from{Aufg1.tex}{body}%
\from{frame.tex}{filler}%
\from{Aufg2.tex}{body}%
\from{frame.tex}{filler}%
\from{frame.tex}{filler}%
\from{frame.tex}{postamble}%
}%
}%
\endbatchfile
Datei: frame.tex
%<*preamble>
\documentclass{article}
\usepackage{amsmath}
%</preamble>
%<*body>
\begin{document}
%</body>
%<filler>\vfill
%<*postamble>
Viel Spass beim Denken.
\end{document}
%</postamble>
Datei: Aufg1.tex
%<*preamble>
\RequirePackage[ngerman]{babel}
\RequirePackage{amssymb}
%</preamble>
%<*body>
Beweisen Sie auf ihrem Heftrand, dass die \(n\)-te Wurzel von
\(a^n+ b^n; a,b,n \in \mathbb{N}\) für \(n>2\) keine ganze Zahl ist.
%</body>
Datei: Aufg2.tex
%<*preamble>
\RequirePackage{listings}
%</preamble>
%<*body>
Was macht das folgende Programm?
\begin{lstlisting}[language=Pascal]
program obscure;
var a, b : longint;
begin
write('Erste Zahl? ');readln(a);
write('Zweite Zahl? ');readln(b);
while a <> b do
begin
If a > b
then a := a mod b
else b := b mod a;
end;
writeln('Ausgabe: ', a);
readln;
end.
\end{lstlisting}
%</body>
Vorschlag 2:
============
Das LaTeX-Kernel-Makro \@ifpackageloaded, welches leider nur in der
Präambel verwendet werden kann, prüft, ob ein Package geladen ist.
Genau genommen prüft es nur, ob das Makro "\ver@<package-name>.sty"
definiert ist.
Daraus abgeleitet kann ich Dir eine einfache Umgebung
"WhenPackageloaded" anbieten -- eine Umgebung und kein Makro, damit
man auch Dinge wie \verb oder die verbatim-Umgebung oder eine
listings-Umgebung darin verwenden kann, was innerhalb von
Makro-Argumenten nicht möglich ist --, welche, was die Argumente angeht,
die selbe Syntax hat, wie der Befehl \usepackage, also
\begin{WhenPackageloaded}[<option-list>]{<package-list>}[<version>]
<body>
\end{WhenPackageloaded}
und hoffentlich folgendes tut:
- Einen \addtocontents-Eintrag ausführen, um in eine externe
Datei einen \RequirePackage-Befehl zu schreiben in der Form
\RequirePackage[<option-list>]{<package-list>}[<version>].
- Prüfen, ob alle im <package-list>-Argument angegebenen
Packages mit den im <option-list>-Argument angegebenen Optionen
geladen sind.
Wenn ja, dann wird nichts weiter getan und der Inhalt/Body der
Umgebung ausgeführt.
Wenn nein, dann wird die comment-Umgebung des verbatim-package
ausgeführt und so der Inhalt/Body der Umgebung
"verschluckt" und für jedes nicht-geladene oder nicht
mit den gewünschten Optionen geladene Package eine
LaTeX-Warnung ausgegeben, dass der Code im Body der
Umgebung in diesem LaTeX-Lauf nicht ausgeführt wurde,
weil besagtes Package nicht geladen ist bzw nicht mit den
benötigten Optionen geladen ist und man LaTeX
nochmal drüberlaufen lassen soll, um beim nächsten
Lauf das Package hoffentlich automatisch (mit den
richtigen Optionen) laden zu lassen.
In der Präambel muss man noch \@starttoc{pkl} ausführen --
\jobname.pkl ist diejenige eben erwähnte externe Datei, in die per
\addtocontents die \Require-Package-Befehle geschrieben werden
und die Datei muss man möglichst bald einlesen, um die Packages
zu laden.
Das bereits von anderen angesprochene Problem, die Reihenfolge, in
der manche Pakete geladen werden müssen, einzuhalten, ist damit
allerdings nicht vollständig gelöst, aber dadurch, dass man wie
bei \usepackage gleich eine ganze <package-list> angeben kann,
sollte man sich in vielen Fällen behelfen können.
Zur Not könnte man wohl auch WhenPackageloaded-Umgebungen ineinander
verschachteln, aber das halte ich nicht für empfehlenswert, weil
damit einhergeht, für jede Schachtelungsebene einen zusätzlichen
LaTeX-Lauf zu brauchen.
Das folgende Beispiel liefert im ersten LaTeX-Lauf nur die
Zeichensequenz "ABC" und den Text für den Fall, dass das verbatim-
Package geladen ist, und anschliessend ein "D".
In den weiteren LaTeX-Läufen werden die übrigen Packages automatisch
geladen und der Code in den Umgebungen wird ausgeführt und man erhält
ein bisschen mehr Text.
Ich habe darauf geachtet, dass man am Beispiel sieht, dass bei der
ganzen Space-Hackerei bspw das Kerning am Umgebungsanfang und -ende
ein wenig flöten geht - Ligaturen und Silbentrennung wohl auch, aber
ich nehme mal an, dass das alles wohl kein wirkliches Problem
darstellt -- wer will schon "kernen" oder Ligaturen oder trennbare
Wörter zusammenbasteln, indem sie/er Dinge von ausserhalb der
Umgebung mit Dingen von innerhalb der Umgebung zusammenfügt?
\documentclass{article}
\usepackage{verbatim}
\makeatletter
\@starttoc{pkl}
\newenvironment{WhenPackageloaded}{%
\@bsphack
\@ifnextchar[{\WhenPackageloaded@I}{\WhenPackageloaded@I[]}%
}{\WhenPackageloaded@IV\@Esphack}%
\@ifdefinable\WhenPackageloaded@I{%
\def\WhenPackageloaded@I[#1]#2{%
\@ifnextchar[%]
{\WhenPackageloaded@II[{#1}]#2}%
{\WhenPackageloaded@II[{#1}]#2[]}%
}%
}%
\@ifdefinable\WhenPackageloaded@II{%
\def\WhenPackageloaded@II[#1]#2[#3]{%
\addtocontents{pkl}{\protect\RequirePackage[{#1}]{#2}[{#3}]}%
% build up a list of calls to |\@onefilewithoptions|
% (one for each package) without thrashing the parameter stack.
\def\reserved@b##1,{%
\ifx\@nil##1\relax\else
\ifx\relax##1\relax\else
\noexpand\WhenPackageloaded@III{##1}{#1}%
\fi
\expandafter\reserved@b
\fi}%
\edef\reserved@a{\zap@space#2 \@empty}%
\edef\reserved@a{\def\noexpand\WhenPackageloaded@IV{\noexpand\iftrue}%
\expandafter\reserved@b\reserved@a,\@nil,}%
{\reserved@a\expandafter}%
\WhenPackageloaded@IV
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\let\WhenPackageloaded@IV=\empty\ignorespaces}%
{\let\WhenPackageloaded@IV=\endcomment\comment}%
}%
}%
\@ifdefinable\my@if@pti@ns{\let\my@if@pti@ns\@if@pti@ns}%
\newcommand*\WhenPackageloaded@III[2]{%
\expandafter\ifx\csname ver@#1.sty\endcsname\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{%
\@latex@warning{Package "#1" not loaded but required for
successful\MessageBreak execution of next bit of code.%
\MessageBreak Rerun LaTeX for having the package loaded
automatically\MessageBreak in the next run for executing
the code following\MessageBreak\expandafter\@firstofone}%
\def\WhenPackageloaded@IV{\iffalse}%
}%
{%
\@expandtwoargs\my@if@pti@ns{%
\@ifundefined{opt@#1.sty}\@empty{\csname opt@#1.sty\endcsname
}}{#2}{}{%
\@latex@warning{Package "#1" not loaded with the options
required for\MessageBreak successful execution of next bit
of code.%
\MessageBreak Rerun LaTeX for hopefully having the package
loaded\MessageBreak automatically in the next run with the
options required for\MessageBreak executing the code following%
}%
\def\WhenPackageloaded@IV{\iffalse}%
}%
}%
}%
\newcommand*\WhenPackageloaded@IV{}%
\makeatother
\begin{document}
A%
\begin{WhenPackageloaded}[ansinew,latin1]{inputenc}
V\par This code is carried out only if package inputenc is loaded.
This should be the case in the second LaTeX-run if aux-files between
\LaTeX-runs are not deleted.\par
\end{WhenPackageloaded}
B%
\begin{WhenPackageloaded}{verbatim, graphics}
V\par This code is carried out only if both package verbatim and
package graphics is loaded. This should be the case in the second
LaTeX-run if aux-files between \LaTeX-runs are not deleted.\par
\end{WhenPackageloaded}
C%
\begin{WhenPackageloaded}{verbatim}
V\par This code is carried out only if package verbatim is loaded.
This should be the case immediately as the verbatim-package is loaded
explicitly in the preamble.\par
\end{WhenPackageloaded}
D
\end{document}
Anmerkung
=========
Zum "modularen" Aufbau kann man einzelne \input-Dateien übrigens auch
so kreieren, dass sie eine externe Präambel ggf zur Laufzeit nachladen.
Als Kriterium kann man bspw nehmen, ob \documentclass bereits auf
\@twoclasseserror gesetzt ist:
preamble.tex:
\expandafter\ifx\csname @twoclasseserror\endcsname\documentclass
\stepcounter{filecnt}%
\expandafter\endinput
\fi
\documentclass{article}
\newcounter{filecnt}%
\stepcounter{filecnt}%
% sonstige Präambel
% sonstige Präambel
\begin{document}%
%%% end of preamble.tex
postamble.tex:
\addtocounter{filecnt}{-1}%
\ifnum\number\value{filecnt} < 1 \else
\expandafter\endinput
\fi
% sonstige Postambel
% sonstige Postambel
\end{document}%
%%% end of postamble.tex
fileA.tex:
\input{preamble}
Text von file A
\input{postamble}
%%% end of fileA.tex
fileB.tex:
\input{preamble}
Text von file B und%
\input{fileA}
\input{postamble}
%%% end of fileB.tex
fileA.tex kann sowohl als main-TeX-file kompiliert werden,
als auch via \input nach fileB.tex importiert werden.
Richtig witzig wird so etwas erst, wenn man \label und \ref in
solchen Dateiverbünden richtig auflösen will - wenn man also
bspw - je nachdem, ob als main-file compiliert oder importiert
wurde - automatisch entweder einen Verweis auf ein anderes/externes
Dokument (bspw mittels XR-package) oder einen Dokument-internen
Verweis kreiert haben möchte, oder auch, wenn Gliederungsebenen
ggf beim Import irgendwie angepasst werden sollen, bspw der
Gliederungsebene, unter der man in die Hauptdatei importiert
hat, untergeordnet werden sollen...
Ulrich
> Mir liegt eine Sammlung von Übungsaufgaben in einzelnen Dateien vor, aus
> denen ich für das zu erzeugende Übungsblatt die passenden durch die
> Angabe des Dateinamens auswähle, d.h. die document-Umgebung der
> Hauptdatei besteht im Wesentlichen aus den Befehlen
>
> \include{Blatt1}
> \include{Blatt2}
> etc. (unter Verwendung des passenden \includeonly-Befehls)
> Nun benötige ich für die ein oder andere Aufgabe ein spezielles Paket,
> z.B. pstricks. Ich möchte jetzt aber nicht in jeder ausgewählten
> Aufgabendatei nachschauen, welches Paket ich dafür noch zusätzlich im
> Hauptdokument laden muss. Das soll in der Aufgabendatei verankert sein
> und beim LaTeX-Lauf berücksichtigt werden. Allerdings bin ich ja zu
> diesem Zeitpunkt bereits aus der Präambel raus und kann nicht mehr
> direkt mit \usepackage arbeiten.
>
> Also habe ich mir den Befehl \Praeambel{arg} geschrieben, der sein
> Argument arg (z.B. \usepackage{pstricks}) in eine externe Datei
> rausschreibt. Beim nächsten LaTeX-Lauf wird diese Datei dann in der
> Praeambel eingelesen.
Erstelle doch einfach für jede Aufgabe eine externe Datei mit den
Paketen vorab und lade die benötigten externen Dateien mit Hilfe der
Liste, die du im \includeonly-Befehl nutzt.
--
Ulrike Fischer
> Das LaTeX-Kernel-Makro \@ifpackageloaded, welches leider nur in der
> Präambel verwendet werden kann,
Paket `ltxcmds' bietet \ltx@ifpackageloaded und co., das diese
Einschränkung nicht hat.
--
Heiko Oberdiek
vielen, vielen Dank für Deine ausführliche Antwort! Bitte habe
Verständnis dafür, dass ich ein wenig Zeit brauchen werde, um insb.
Vorschlag 2 zu verstehen und die Vor- und Nachteile beider Vorschläge
bewerten zu können.
Gruß, Claas
PS: Auch vielen herzlichen Dank an alle anderen, die sich für mich den
Kopf zerbrochen haben!
Bei meinem Vorschlag 1 habe ich übersehen, dass Du beim
Compilieren alles auf einen Rutsch haben wolltest.
Anstatt zuerst die Datei "main.tex" zu compilieren und dann die
Datei "NeueAufgabenZusammenstellung.tex" zu compilieren, kannst Du
auch innerhalb von main.tex via \input die Datei
"NeueAufgabenZusammenstellung.tex" aufrufen und nur main.tex mit
LaTeX compilieren.
Wenn man von den folgenden vier Dateien die Datei main.tex mit
LaTeX compiliert, wird
- erstens eine neue Datei erzeugt, mit Namen
"NeueAufgabenZusammenstellung.tex". Die wiederum stellt
den compilierbaren Quellcode für ein fertiges Dokument dar.
In diesem Quellcode ist Zeug, was in die Präambel gehört, in der
Präambel, und Zeug, was in den "body" der document-Umgebung
gehört, befindet sich im "body" der document-Umgebung.
- zweitens diese neue Datei per \input geladen, sodass man
auch gleich das fertige dvi/pdf-Dokument als main.dvi/main.pdf
bekommt.
(Lustigerweise kann ich main.tex auch durch MiKTeX-texify
compilieren lassen. texify ruft so viele LaTeX-Läufe auf, wie nötig,
um das Dokument zu compilieren.)
Datei main.tex:
\IfFileExists{NeueAufgabenZusammenstellung.tex}%
{\csname @gobble\endcsname}{}%
{%
\begingroup
\input docstrip
\nopreamble
\nopostamble
\generate{%
\file{NeueAufgabenZusammenstellung.tex}{%
\from{frame.tex}{preamble}%
\from{Aufg1.tex}{preamble}%
\from{Aufg2.tex}{preamble}%
\from{frame.tex}{body}%
\from{Aufg1.tex}{body}%
\from{frame.tex}{filler}%
\from{Aufg2.tex}{body}%
\from{frame.tex}{filler}%
\from{frame.tex}{filler}%
\from{frame.tex}{postamble}%
}%
}%
\iftopbatchfile\ReportTotals\fi
\endgroup
}%
\input NeueAufgabenZusammenstellung.tex
Datei: frame.tex
%<*preamble>
\documentclass{article}
\usepackage{amsmath}
%</preamble>
%<*body>
\begin{document}
%</body>
%<filler>\vfill
%<*postamble>
Viel Spass beim Denken.
\end{document}
%</postamble>
Datei: Aufg1.tex
%<*preamble>
\RequirePackage[latin1]{inputenc}
Datei: Aufg2.tex
Ulrich
> Bitte habe
> Verständnis dafür, dass ich ein wenig Zeit brauchen werde, um insb.
> Vorschlag 2 zu verstehen und die Vor- und Nachteile beider Vorschläge
> bewerten zu können.
Die Grundidee ist:
Sofern vorhanden, wird am Anfang des LaTeX-Laufes eine externe Datei
(mittels \@starttoc} eingelesen, welche Direktiven für das Laden weiterer
Packages enthält.
Die Umgebung WhenPackageloaded schreibt gemäß den ihr
übergebenen Argumenten (mittels \addtocontents) eine solche
Direktive in die besagte externe Datei.
[
Die Argumente dieser Umgebung entsprechen der Syntax von
\usepackage/\Requirepackage:
\usepackage[<option-list>]{<package-list>}[<Version>]
\begin{WhenPackageloaded}[<option-list>]{<package-list>}[<Version>]
]
Sodann prüft sie, ob in diesem LaTeX-Lauf alle in ihrem
<package-list>-Argument angegebenen Packages mit den
in ihrem <option-list>-Argument angegebenen Optionen
geladen sind.
Wenn ja, wird der "Body" der Umgebung ausgeführt.
Wenn nein,
- wird intern die comment-Umgebung des
verbatim-package auf den "Body" der Umgebung
angewandt, sodass der "verschluckt" wird, ohne
Fehlermeldungen zu verursachen.
- wird eine Warnmeldung ausgegeben, dass man
LaTeX nochmal laufen lassen soll.
Im nächsten Lauf ist nämlich die zuvor geschriebene
\RequirePackage-Direktive in der zu Anfang des
LaTeX-Laufes per \@starttoc zu ladenden externen
Datei enthalten, sodass dann die Packages, so wie
man sie braucht, geladen sein müssten und man bei
der Prüfung dann im "Wenn ja"-Zweig landet und der
Body der Umgebung ausgeführt wird.
Wie die Umgebung ihre Argumente einlesen muss,
habe ich abgekupfert aus dem LaTeX-Quellcode,
File L: ltclass.dtx,
\RequirePackage
-> \@fileswithoptions
-> \@fileswith@ptions
-> \@fileswith@pti@ns
und für den Anfang beim Abkupfern erstmal überall
dasjenige Argument "wegoperiert", welches lediglich
das Token \@pkgextension (oder \@clsextension)
enthält und dafür gleich die Sequenz "sty" angenommen
und auch gleich alle Verzweigungen auf den "Ast"
reduziert, der im Falle "\@pkgextension" bzw im
Fall "nicht-\@clsextension" ausgeführt wird.
Vom Argumenteinlesen her ist analog
die Umgebung WhenPackageloaded zu \@fileswithoptions
das Makro \WhenPackageloaded@I zu \@fileswith@ptions
das Makro \WhenPackageloaded@II zu \@fileswith@pti@ns
So, wie durch \@fileswith@pti@ns mittels \edef und
\reserved@b ein Makro \reserved@a erzeugt wird, welches
für jedes package der Liste einen Aufruf des Makros
\@onefilewithoptions enthält, um dieses Package zu laden, wird
durch \WhenPackageloaded@II mittels \edef und
\reserved@b ein Makro \reserved@a erzeugt, welches
für jedes Package der Liste einen Aufruf des Makros
\WhenPackageloaded@III enthält, welches also eine
Liste an Anufrufen des Makros \WhenPackageloaded@III
enthält.
Wenn \reserved@a ausgeführt wird, werden sukzessive
alle diese \WhenPackageloaded@III-Aufrufe mit dem
jeweiligen-Package-Namen und der Option-List als
Argument ausgeführt.
\WhenPackageloaded@III prüft, ob das jeweilige
Package mit den angegebenen Optionen geladen ist
und wenn nein, definiert es das eingangs zu \iftrue
definierte Makro \WhenPackageloaded@IV zu
\iffalse um und gibt eine Warnmeldung aus, dass
das Package nicht geladen ist.
(Den Test, ob ein Package geladen ist, habe ich in gleicher
Weise von \@ifpackageloaded (bzw \@ifl@aded) und
\@ifpackagewith (bzw \@if@ptions -> \@if@pti@ns)
abgekupfert.)
Wenn also alle \WhenPackageloaded@III-Aufrufe
abgearbeitet sind, ist \WhenPackageloaded@IV
entweder \iftrue oder \iffalse und man kann damit
verzweigen, ob die comment-Umgebung gestartet,
oder ob ob der body der Umgebung ausgeführt
werden soll.
Im ersten Fall muss man am Ende der Umgebung die
comment-Umgebung auch wieder beenden und dazu
ird vor dem Aufruf des \comment-Makro das Makro
\WhenPackageloaded@IV dann gleich \endcomment gesetzt.
Im zweiten Fall muss man das nicht, sollte aber Leerzeichen
zum Anfang der Umgebung mittels \ignorespaces ignorieren,
nachdem man das Makro \WhenPackageloaded@IV
gleich \empty gesetzt hat.
Am Ende der Umgebung lässt man dann noch
\WhenPackageloaded@IV ausführen - im einen Fall
beendet es die intern gestertete comment-Umgebung,
im anderen Fall tut es nichts (bzw expandiert zu \empty,
was wiederum zu nichts expandiert).
Ich habe in meinem gestrigen Posting übrigens im Tran behauptet,
man könne zur Not WhenPackageloaded-Umgebungen ineinander
verschachteln. Das war falsch und man sollte das unterlassen, weil
es in dem Moment in die Hosen geht, wo intern die comment-
Umgebung ausgeführt wird, genauso, wie es in die Hosen geht,
verbatim-Umgebungen ineinander zu verschachteln.
Ulrich