Menu

HowTo_ChapterAtLists

Wie man Kapitelüberschriften im Abbildungs- und Tabellenverzeichnis und in anderen Verzeichnissen von Gleitumgebungen ausgeben kann

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.


Related

Wiki (Deutsch): HowTo_ToCConfiguration

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.