Wer die KOMA-Script-Anleitung gelesen hat weiß, dass man bei scrbook
und scrreprt
die Kapitelüberschriften mit Hilfe der Option chapteratlists=entry
zusätzlich zum Inhaltsverzeichnis auch in allen Verzeichnissen von Gleitumgebungen anzeigen lassen kann. Allerdings arbeitet die Option sehr konsequent und fügt die Kapitelüberschrift beispielsweise auch dann ins Abbildungsverzeichnis, wenn das entsprechende Kapitel gar keine Abbildungen hat und daher das Abbildungsverzeichnis für dieses Kapitel auch keine Abbildungen anzeigt. Häufig wird jedoch gewünscht, dass die Kapitelüberschrift nur dann ausgegeben wird, wenn dieses Kapitel auch einen entsprechenden Gleitumgebungseintrag besitzt.
Das Schreiben der Kapiteleinträge in die Verzeichnisse erfolgt bei den beiden Klassen innerhalb von \addchaptertocentry
. Diese Anweisung wird von \chapter
(oder \addchap
) aufgerufen, also zu einem Zeitpunkt, wenn noch gar nicht bekannt ist, ob das Kapitel nachfolgend eine entsprechende Gleitumgebung haben wird. Also benötigen wir zunächst einen Indikator dafür. Da alle Einträge per \addcontentsline
geschrieben werden, liegt die Idee nahe, innerhalb von \addcontentsline
auch diesen Indikator zu generieren. Da der Indikator im nächsten LaTeX-Lauf zur Verfügung stehen muss, wird er in die aux
-Datei geschrieben. Am einfachsten geht das, indem man ein Label generiert:
\AddToHookWithArguments{cmd/addcontentsline/before}{%
\Ifstr{#1}{\ext@toc}{}{%
\@ifundefined{chapter@\thechapter @has@#1@done}{%
\expandafter\global\@namedef{chapter@thechapter @has@#1@done}{true}%
\label{chapter@\thechapter @has@#1}%
}{}%
}%
}
Wir verwenden hier einen generischen LaTeX-Hook for den Anfang des Befehls \addcontentsline
, der auch alle Argumente für \addcontentsline
erhält. Das erste Argument ist dabei die Dateierweiterung des jeweiligen Verzeichnisses. Hier testen wir zunächst, dass es sich nicht um das Inhaltsverzeichnis selbst handelt und erzeugen den Indikator nur dann. Das ist zwar nicht zwingend notwendig aber durchaus sinnvoll.
Wir verwenden deshalb ein Label als Indikator, weil wir in aktuellen LaTeX-Versionen sehr einfach mit \IfLabelExists:TF
auf dessen Existenz testen können und gleichzeitig LaTeX bei Veränderungen automatisch einen Hinweis am Ende des LaTeX-Laufs ausgibt, so dass wir wissen, dass ein weiterer LaTeX-Lauf notwendig ist. Der Name des Labels setzt sich einfach aus der Kapitelnummer und der Dateierweiterung des jeweiligen Verzeichnisses sowie einigen sinnvollen Strings zusammen. Die Nummer des Kapitels erhalten wir (in dieser ersten Version) einfach per \thechapter
.
Da jedoch mehrfach definierte Labels zu Warnungen führen, verwenden wir einen zweiten Indikator für die Entscheidung, ob das Label noch definiert werden muss oder das aktuelle Kapitel bereits ein Label erzeugt wurde. Dafür definieren wir global eine weitere Anweisung und setzen das Label nur dann, wenn diese Anweisung noch nicht definiert ist.
Als nächstes müssen wir dafür sorgen, dass der Kapiteleintrag nur geschrieben wird, wenn das Label für dieses Kapitel existiert. Dazu muss lediglich die ToC-Eigenschaft chapteratlist
abhängig davon gesetzt oder gelöscht werden, ob das Indikator-Label existiert. Auch hierfür müssen wir \addchaptertocentry
nicht komplett umdefinieren, sondern können einen generischen LaTeX-Hook am Anfang des Befehls verwenden:
\AddToHook{cmd/addchaptertocentry/before}{%
\if@chaptertolists
\doforeachtocfile[float]{%
\IfLabelExistsTF{chapter@\thechapter @has@\@currext}{%
\setuptoc{\@currext}{chapteratlist}%
}{%
\unsettoc{\@currext}{chapteratlist}%
}%
}%
\fi
}
Mit \if@chaptertolists
prüfen wir, ob die Option chapteratlists
überhaupt verwendet wird. Genau genommen könnten wir auf diesen Test auch verzichten. Dann prüfen wir für jede Hilfsdatei der Kategorie float
, of das entsprechende Indikator-Label für das aktuelle Kapitel existiert. Ist das der Fall, setzen wir die Eigenschaft chapteratlist
für die entsprechende Dateierweiterung. Ist es nicht der Fall, löschen wir die Eigenschaft.
Das war es eigentlich schon. Allerdings hat die Verwendung von \thechapter
einen entscheidenden Nachteil. Das Ganze funktioniert nicht korrekt, wenn nicht nur \chapter
, sondern auch \addchap
verwendet wird. Auch sonstige nicht nummerierte Kapitel, beispielsweise im Bereich von \frontmatter
oder \backmatter
stellen ein Problem dar. Um das Problem zu lösen, können wir einen absoluten Kapitelzähler abschapter
verwenden, der auch nicht nummerierte Kapitel zählt. Dieser kann ebenfalls per generischem Hook bei jedem \chapter
(und damit auch jedem \chapter*
und jedem \addchap
oder \addchap*
) erhöht werden. Dann muss in obigen Definitionen nur noch \thechapter
durch \theabschapter
ersetzt werden.
Hier ein vollständiges Beispiel:
\documentclass[chapteratlists=entry]{scrbook}
% Code to limit chapteratlists=entry to chapters with float entries.
% → https://sf.net/p/koma-script/wiki-de/HowTo_ChapterAtLists
\makeatletter
\newcounter{abschapter}
\AddToHook{cmd/chapter/before}{\stepcounter{abschapter}}
\AddToHookWithArguments{cmd/addcontentsline/before}{%
\Ifstr{#1}{\ext@toc}{}{%
\@ifundefined{chapter@\theabschapter @has@#1@done}{%
\expandafter\global\@namedef{chapter@\theabschapter @has@#1@done}{true}%
\label{chapter@\theabschapter @has@#1}%
}{}%
}%
}
\AddToHook{cmd/addchaptertocentry/before}{%
\if@chaptertolists
\doforeachtocfile[float]{%
\IfLabelExistsTF{chapter@\theabschapter @has@\@currext}{%
\setuptoc{\@currext}{chapteratlist}%
}{%
\unsettoc{\@currext}{chapteratlist}%
}%
}%
\fi
}
\makeatother
\usepackage{mwe}
\begin{document}
\tableofcontents
\listoffigures
\listoftables
\Blinddocument
\begin{figure}
\centering
\includegraphics{example-image}
\caption{Test Figure}
\label{fig:test}
\end{figure}
\Blinddocument
\begin{table}
\centering
\begin{tabular}{ll}
test & table
\end{tabular}
\caption{Test Table}
\label{tab:test}
\end{table}
\Blinddocument
\Blinddocument
\begin{figure}
\centering
\includegraphics{example-image-a}
\caption{Test Figure A}
\label{fig:testA}
\end{figure}
\Blinddocument
\begin{table}
\centering
\begin{tabular}{ll}
test & table
\end{tabular}
\caption{Test Table A}
\label{tab:testA}
\end{table}
\addchap{Test addchap}
\begin{table}
\renewcommand*{\thetable}{\arabic{table}}%
\renewcommand*{\theHtable}{\theabschapter.\arabic{table}}%
\centering
\begin{tabular}{ll}
test & test
\end{tabular}
\caption{Test Table addchap}
\label{tab:addchap}
\end{table}
\addchap{Another addchap}
\blindtext
\appendix
\Blinddocument
\begin{table}
\centering
\begin{tabular}{ll}
test & table
\end{tabular}
\caption{Test Table B}
\label{tab:testB}
\end{table}
\Blinddocument
\end{document}
Das Beispiel funktioniert übrigens auch dann noch, wenn man hyperref
lädt, wobei es egal ist, ob man das Paket vor oder nach dem zusätzlichen Präambelcode lädt.