Sie sind hier

Transparente Klassenoptionen bei Wrapper-Klassen

Hallo Markus,
ich habe mich gerade bei goLaTeX angemeldet, weil mein Anliegen nichts speziell mit den KOMA-Script-Klassen zu tun hat. Erst danach habe ich aber gesehen, dass du auf dieser Plattform ja gar nicht mehr zu finden bist. Falls du Zeit und Lust hast wäre es schön, wenn du auf meine Frage trotzdem eine Antwort geben könntest. Zumindest falls dort keine dir zusagende Antwort auftauchen sollte.

Gruß
Falk

Bild von Markus Kohm

Ich habe keinen Account mehr für goLaTeX.

Als Lösung käme aber beispielsweise

\begin{filecontents*}{\jobname.cls}
\DeclareOption{newopt}{%
  \AtEndOfClass{\renewcommand*{\chapterheadendvskip}{\vspace*{5\baselineskip}}}%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrreprt}}
\ProcessOptions*\relax
\LoadClass{scrreprt}
\end{filecontents*}
\documentclass[chapterprefix,newopt]{\jobname}
\usepackage{blindtext}
\begin{document}
\blinddocument
\end{document}

in Frage. Man könnte auch einen Schalter (\newif) definieren und darüber arbeiten. Die Anweisung \LoadClassWithOptions ist leider ziemlich nutzlos, so wie sie in LaTeX definiert ist. Die kann man wirklich nur verwenden, wenn man eine Wrapper-Klasse ohne eigene Optionen definiert (oder sich um die falschen Warnungen nicht weiter schert). Ich glaube, ich habe das bereits 1993/1994 bemängelt, als ich die KOMA-Script-Klassen ursprünglich nur als Wrapper-Klassen zu den Standardklassen definieren wollte. Das war noch vor dem LaTeX-Bug-Tracker, zu dem ich damals noch keinen Zugang hatte.

Danke für die erste Lösung. Ich habe gedacht, mit diesem einfachen Beispiel könnte das Problem für mich gelöst werden. Allerdings muss ich da noch einmal nachhaken. Für den Fall, dass ich die Möglichkeiten nutzen möchte, die mir scrbase bietet -- unter anderem auch die späte Optionenwahl -- funktioniert die Lösung leider nicht mehr:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.cls}
%\LoadClassWithOptions{scrreprt}
\RequirePackage{scrbase}
\DefineFamily{TUD}
\DefineFamilyMember{TUD}%
\newif\if@newopt
\DefineFamilyKey{TUD}{newopt}[true]{%
  \AtEndOfClass{%
    \FamilySetBool{TUD}{newopt}{@newopt}{#1}
    \if@newopt%
      \renewcommand*{\chapterheadendvskip}{\vspace*{5\baselineskip}}%
    \else%
      \renewcommand*{\chapterheadendvskip}{\vspace*{-.5\baselineskip}}%
    \fi%
  }%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrreprt}}
\FamilyProcessOptions{TUD}
\LoadClass{scrreprt}
\end{filecontents*}
\documentclass[chapterprefix,newopt=no]{\jobname}
\usepackage{blindtext}
\begin{document}
% das geht nun verständlicher Weise nicht mehr
%\FamilyOptions{TUD}{newopt=no}
\blinddocument
\end{document}

Wäre es denkbar, dass scrbase dahingehend erweitert wird, dass ich mich als Klassenautor um dieses Thema nicht mehr kümmern muss? Ich finde es schon ein wenig umständlich, wenn ich für jede Option, die ich definiere, noch daran denken muss, mich um dieses Problem zu kümmern. Vielleicht hast du ja eine einfache Lösung parat. Vielen Dank für deine Hilfe.

Bild von Markus Kohm

Auch das ist kein Problem:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.cls}
\RequirePackage{scrbase}
\newcommand*{\package@noworlater}{%
  \AtEndOfClass
}
\AtEndOfClass{\let\package@noworlater\@firstofone}
\DefineFamily{TUD}
\DefineFamilyMember{TUD}%
\newif\if@newopt
\DefineFamilyKey{TUD}{newopt}[true]{%
  \package@noworlater{%
    \FamilySetBool{TUD}{newopt}{@tempswa}{#1}
    \if@tempswa%
      \renewcommand*{\chapterheadendvskip}{\vspace*{5\baselineskip}}%
    \else%
      \renewcommand*{\chapterheadendvskip}{\vspace*{-.5\baselineskip}}%
    \fi%
  }%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrreprt}}
\FamilyProcessOptions{TUD}
\LoadClass{scrreprt}
\end{filecontents*}
\documentclass[chapterprefix,newopt=no]{\jobname}
\usepackage{blindtext}
\begin{document}
\FamilyOptions{TUD}{newopt=no}
\blinddocument
\end{document}

Allerdings würde ich Dir empfehlen, bei Verwendung der Optionen von scrbase, Dir die aktuelle SVN-Version von KOMA-Script zu besorgen. Ich habe diesbezüglich nämlich ein paar Änderungen vorgenommen, mit denen es endlich möglich ist, dass unterschiedliche Pakete auf unterschiedliche Werte desselben Schlüssels reagieren. Ich brauche das beispielsweise, um via zukünftigem Nachfolger von scrpage2 Optionen der KOMA-Script-Klassen zu erweitern.

Danke Markus, damit kann ich leben. Allerdings wäre es für mich natürlich bequemer, wenn ich nicht im Quelltext durch alle Optionen laufen müsste, um das Verhalten zu ändern sondern einfach an einer Stelle anpacken könnte. Ich gehe dabei bei der Definition von Optionen ähnlich vor, wie du das für KOMA-Script selber machst:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.cls}
\RequirePackage{scrbase}
\newcommand*{\package@noworlater}{%
  \AtEndOfClass
}
\AtEndOfClass{\let\package@noworlater\@firstofone}
\DefineFamily{TUD}
\newcommand*\TUD@key[1][.\@currname.\@currext]{%
  \DefineFamilyMember{TUD}%
  \DefineFamilyKey[#1]{TUD}%
}
\newif\if@newopt
\TUD@key{newopt}[true]{%
  \package@noworlater{% kriegt man das in die Definition von \TUD@key?
    \FamilySetBool{TUD}{newopt}{@tempswa}{#1}
    \if@tempswa%
      \renewcommand*{\chapterheadendvskip}{\vspace*{5\baselineskip}}%
    \else%
      \renewcommand*{\chapterheadendvskip}{\vspace*{-.5\baselineskip}}%
    \fi%
  }%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrreprt}}
\FamilyProcessOptions{TUD}
\LoadClass{scrreprt}
\end{filecontents*}
\documentclass[chapterprefix,newopt]{\jobname}
\usepackage{blindtext}
\begin{document}
\chapter{Erstes Kapitel}
\blindtext
\FamilyOptions{TUD}{newopt=no}
\chapter{Zweites Kapitel}
\blindtext
\end{document}

Da \DefineFamilyKey selbst wiederum auf \define@key zugreift, weiß ich nicht, wie ich \package@noworlater innerhalb von \TUD@key verwenden kann, ohne auf die internen Befehle des keyval-Paketes zurückzugreifen. Falls das zu umständlich sein sollte, nutze ich einfach die bereits funktionierende Lösung.

Bezüglich der SVN-Version muss ich sagen, dass ich diese sehr gerne nutzen würde. Allerdings kann ich das nicht von den Anwendern meiner Klassen erwarten. Deshalb würde ich gerne mit der aktuellen Verison weiter arbeiten. Sollte sich durch die neue Version KOMA-Script ein Problem wesentlich eleganter oder gar überhaupt nur so lösen lassen, werde ich natürlich darauf zurückgreifen. Allerdings auch dann erst, wenn diese Version über CTAN verfügbar ist.

Bild von Markus Kohm

Sollte auch gehen, ohne auf interne Anweisungen von keyval zurück zu greifen. Es ist etwas umständlich, weil LaTeX selbst wenig bietet, um Anweisungen mit mehreren optionalen Argumenten zu definieren, aber probier mal:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.cls}
\RequirePackage{scrbase}
\newcommand*{\TUD@noworlater}{%
  \AtEndOfClass
}
\AtEndOfClass{\let\TUD@noworlater\@firstofone}
\DefineFamily{TUD}
\newcommand*\TUD@key[2][.\@currname.\@currext]{%
  \DefineFamilyMember{TUD}%
  \@ifnextchar[{\TUD@@key[#1]{#2}}{\DefineFamilyKey{#1}{TUD}{#2}}%
}
\def\TUD@@key[#1]#2[#3]#4{%
  \DefineFamilyKey[#1]{TUD}{#2}[{#3}]{\TUD@noworlater{#4}}%
}
\newif\if@newopt
\TUD@key{newopt}[true]{%
    \FamilySetBool{TUD}{newopt}{@tempswa}{#1}
    \if@tempswa%
      \renewcommand*{\chapterheadendvskip}{\vspace*{5\baselineskip}}%
    \else%
      \renewcommand*{\chapterheadendvskip}{\vspace*{-.5\baselineskip}}%
    \fi%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrreprt}}
\FamilyProcessOptions{TUD}
\LoadClass{scrreprt}
\end{filecontents*}
\documentclass[chapterprefix,newopt]{\jobname}
\usepackage{blindtext}
\begin{document}
\chapter{Erstes Kapitel}
\blindtext
\FamilyOptions{TUD}{newopt=no}
\chapter{Zweites Kapitel}
\blindtext
\end{document}

Danke Markus, so funktioniert alles. Ich musste noch den Fall anpassen, wenn der Option kein Default-Wert zugewiesen wurde.

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.cls}
\RequirePackage{scrbase}
\newcommand*\TUD@noworlater{\AtEndOfClass}
\AtEndOfClass{\let\TUD@noworlater\@firstofone}
\DefineFamily{TUD}
\newcommand*\TUD@key[2][.\@currname.\@currext]{%
  \DefineFamilyMember{TUD}%
  \@ifnextchar[{\TUD@@key[#1]{#2}}{\TUD@@@key[#1]{#2}}%
}
\def\TUD@@key[#1]#2[#3]#4{%
  \DefineFamilyKey[#1]{TUD}{#2}[{#3}]{\TUD@noworlater{#4}}%
}
\def\TUD@@@key[#1]#2#3{%
  \DefineFamilyKey[#1]{TUD}{#2}{\TUD@noworlater{#3}}%
}
\newif\if@newopt
\TUD@key{newopt}{%
  \FamilySetBool{TUD}{newopt}{@tempswa}{#1}
  \if@tempswa%
    \renewcommand*{\chapterheadendvskip}{\vspace*{5\baselineskip}}%
  \else%
    \renewcommand*{\chapterheadendvskip}{\vspace*{-.5\baselineskip}}%
  \fi%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrreprt}}
\FamilyProcessOptions{TUD}
\LoadClass{scrreprt}
\end{filecontents*}
\documentclass[chapterprefix,newopt=on]{\jobname}
\usepackage{blindtext}
\begin{document}
\chapter{Erstes Kapitel}
\blindtext
\FamilyOptions{TUD}{newopt=no}
\chapter{Zweites Kapitel}
\blindtext
\end{document}
Comments for "Transparente Klassenoptionen bei Wrapper-Klassen" abonnieren