Sie sind hier

Verzögern des Ladens eines Pakets

Hallo,
ich würde gerne das Laden eines Paketes -- für den Fall, dass es der Anwender anfordert -- bis zu einem bestimmten Zeitpunkt verzögern.

Ich habe in meiner Klasse einen Teil, den ich mit \AtBeginDocument verzögere. Erst danach -- und auch nur wenn es angefordert ist -- soll das Paket geladen werden. Gibt es eine Möglichkeit, dies beispielsweise mit dem Paket scrlfile zu bewerkstelligen? Prinzipiell müsste man ja das direkte Laden des Pakets mit \usepackage{meinpaket} verhindern, sich merken, dass das Paket meinpaket angefordert wurde und später im entsprechenden Teil des Quelltextes eine Abfrage in dem Stil \ifpackagewasrequested{meinpaket}{\usepackage{meinpaket}}{} implementieren. Geht das irgendwie?

Grüße
Falk

Bild von maphy-psd

Das ist ganz einfach mit

\AfterPackage{Paket}{Anweisungen}

zu bewerkstelligen. Siehe scrguide.pdf, Abschnitt 11.2., Seite 271.

Vielleicht habe ich mich nicht deutlich genug ausgedrückt. Der Teil meines Quelltextes innerhalb von \AtBeginDocument soll auf jeden Fall ausgeführt werden, unabhängig davon, ob meinpaket geladen wird oder nicht. Wenn es geladen wird, soll dies erst nach dem Teil des Quelltextes geschehen. Man könnte jetzt dem Anwender in der Dokumentation den Hinweis geben, dass er meinpaket nur in der Form \AtBeginDocument{\usepackage{meinpaket}} laden soll, aber intuitiv und fehlerunanfällig ist das nicht.

Die Variante \AfterPackage würde mir gar nicht helfen, mit \BeforePackage würde der Quelltext ja nur ausgeführt, wenn das Paket tatsächlich geladen wird.

Bild von Markus Kohm

Du schreibst ein Paket meinpaketersatz:

\ProvidesPackage{meinpaketersatz}[2013/11/15 v0.1 demo package]
\newcommand*{\meinpaketersatzoptionen}{}
\DeclareOption*{%
  \edef\meinpaketersatzoptionen{%
    \ifx\meinpaketersatzoptionen\@empty\else,\fi
    \CurrentOption
  }%
}
\ProcessOptions\relax
\newcommand*{\lademeinpaket}{%
  % Jetzt kommt ein Hack, damit das Paket doch noch geladen werden kann:
  \expandafter\let\csname meinpaket.sty-@aliasname\endcsname\relax
  % und dann wird das Paket geladen:
  \expandafter\RequirePackage\expandafter[\meinpaketersatzoptionen]{meinpaket}%
}

Und in Deiner Klasse verwendest Du dann folgenden Code:

\RequirePackage{scrlfile}
\ReplacePackage{meinpaket}{meinpaketersatz}
\AtBeginDocument{%
  % Hier der Code, der vor dem Laden des Pakets auszuführen ist
  \csname lademeinpaket\endcsname
}

Mangels vollständigem Minimalbeispiel habe ich das nicht getestet, aber es sollte funktionieren. Prinzipiell könnte die Klasse meinpaketersatz.sty sogar selbst in das aktuelle Arbeitsverzeichnis schreiben. Dann ist man von eventuellen Fehlinstallationen unabhängig.

Eine andere Variante wäre, wenn der Code nicht zwingend per \AtBeginDocument, sondern nur zwingend vor dem Laden des Pakets auszuführen wäre. Dann würde ich den ganzen Code in ein Makro stecken, das sich als erstes selbst auf \relax setzt, dieses Makro per \BeforePackage ausführen und per \AtBeginDocument noch einmal ausführen, also beispielsweise:

\newcommand*{\machdasvormeinpaket}{%
  \let\machdasvormeinpaket\relax
  \typeout{Achtung, gleich wird meinpaket geladen oder das Dokument begonnen!}%
}
\BeforePackage{meinpaket}{\machdasvormeinpaket}
\AtBeginDocument{\machdasvormeinpaket}

Dabei steht die \typeout-Anweisung quasi als Platzhalter für die Dinge, die vor dem Laden von meinpaket, aber spätestens während \begin{document} erledigt werden sollen.

Die zweite Variante ist sicher die einfachere Lösung, wenn sie denn in Frage kommt.

Ab KOMA-Script 3.12 gibt es noch eine dritte Möglichkeit:

\newif\if@pleaseloadmeinpaket
\PreventPackageFromLoading[\@pleaseloadmeinpakettrue]{meinpaket}
\AtBeginDocument{%
  \if@pleaseloadmypackage
    \typeout{Jetzt laden wir meinpaket und alle davon geladenen Pakete also doch noch!}%
    % Alles, was vor dem Laden passieren soll
    \UnPreventPackageFromLoading*{meinpaket}% Paket darf wieder geladen werden
    \RequirePackage{meinpaket}%
  \fi
}

Hallo Markus,

danke dir für die Hilfe. Es ist leider etwas umständlich, für jedes Paket, welches potentiell Probleme machen könnte, ein eigenes Ersatzpaket zu schreiben. Wenn, dann würde ich wahrscheinlich tatsächlich mit der filecontents-Umgebung arbeiten. Ich werde noch einmal meinen Quelltextprüfen und ggf. überarbeiten, um mit \BeforePackage arbeiten zu können. Nochmals vielen Dank für deine Mühen.

Grüße
Falk

Bild von Markus Kohm

Es gibt zukünftig auch noch eine dritte Möglichkeit, die ich in meiner Antwort noch ergänzt habe.

...fantastisch. Danke dir für deine Hilfe.

Beste Grüße
Falk

Edit:
Wenn ich das richtig sehe, fehlt in deinem Codefragment der Befehl \ResetPreventPackageFromLoading und bei \PreventPackageFromLoading hat sich ein Tippfehler eingeschlichen -- das "n" fehlt.

Bild von Markus Kohm

Es geht jetzt ohne das Zwischenspeichern der Verhinderungsliste.

Hallo,

gibt es eine Möglichkeit, beim verzögerten Laden eines Paketes die vom Anwender angegebenen Paketoptionen aufzugreifen und an das Paket weiterzureichen? Der Nutzer verwendet beispielsweise

\usepackage[optionA,optionB]{meinpaket}

und ich würde das in der Wrapper-Klasse mit

\newif\if@pleaseloadmeinpaket
\PreventPackageFromLoadingSaveOptions[\@pleaseloadmeinpakettrue]{meinpaket}
\AtBeginDocument{%
  \if@pleaseloadmypackage
    \typeout{Jetzt laden wir meinpaket und alle davon geladenen Pakete also doch noch!}%
    % Alles, was vor dem Laden passieren soll
    \UnPreventPackageFromLoading*{meinpaket}% Paket darf wieder geladen werden
    \PassOptionsToPackage{\meinpaket@savedoptions}{meinpaket}%
    \RequirePackage{meinpaket}%
  \fi
}

abfangen. Ist das in irgendeiner Form darstellbar?

Grüße
Falk

Bild von Markus Kohm

Die einzige Möglichkeit, die ich mir derzeit vorstellen könnte, wäre im optionalen Code von \PreventPackageFromLoading an die Optionen für das vom Laden verhinderten Pakets zu gelangen. Dafür sehe ich aber im Augenblick keine saubere Möglichkeit. Mit einem Hack, wäre es möglich:

\documentclass{scrartcl}
 
\makeatletter
\newif\if@pleaseloadmeinpaket
\newcommand*{\meinpaket@savedoptions}{}
\newcommand*{\this@were@the@options}{}
\usepackage{xpatch}% etoolbox genügt in dem Fall nicht!
\xpretocmd{\scrlfile@RequirePackage}{\def\this@were@the@options{#1}}{}{\PaTChFailed}
\PreventPackageFromLoading[%
  \@pleaseloadmeinpakettrue
  \let\meinpaket@savedoptions\this@were@the@options
]{meinpaket}
\AtBeginDocument{%
  \if@pleaseloadmeinpaket% DAS WAR FALSCH!!!
    \typeout{Jetzt laden wir meinpaket und alle davon geladenen Pakete also doch noch!}%
    % Alles, was vor dem Laden passieren soll
    \UnPreventPackageFromLoading*{meinpaket}% Paket darf wieder geladen werden
    \PassOptionsToPackage{\meinpaket@savedoptions}{meinpaket}%
    \show\meinpaket@savedoptions% Zu Demozwecken genügt das …
%    \RequirePackage{meinpaket}% … an Stelle von dem
  \fi
}
\usepackage[optionA,optionB]{meinpaket}
 
\begin{document}
 
\end{document}

Dieser Hack sollte so lange funktionieren, solange sich \scrlfile nicht so gravierend ändert, dass das erste Argument nicht mehr die Optionen sind oder die Anweisung gar nicht mehr verwendet wird.

Hallo Markus,

danke für die Hilfe. Ich versuche zumeinst auf einen Patch von Befehlen zu verzichten, damit sich der Wartungsaufwand bei der Änderung eines Pakets in Grenzen hält. Deine Lösung funktioniert soweit. Wahrscheinlich werde ich diese aber nich umsetzen und stattdessen an den Anwender im Zweifelsfall ein Warnung mit einem Hinweis, wann das fragliche Paket geladen werden sollte, ausgeben. Trotzdem vielen Dank für deine Mühen.

Grüße
Falk

Comments for "Verzögern des Ladens eines Pakets" abonnieren