Anyone who has read the KOMA-Script user guide knows that with scrbook
and scrreprt
the chapter headings can also be displayed in all directories of floating environments using the option chapteratlists=entry
in addition to the table of contents. However, the option works very consistently and adds the chapter heading to the list of figures, for example, even if the corresponding chapter has no figures at all and therefore the list of figures for this chapter does not display any figures. However, it is often desired that the chapter heading is only displayed if this chapter also has a corresponding floating environment entry.
The chapter entries are written to the directories in both classes within \addchaptertocentry
. This instruction is called by \chapter
(or \addchap
), i.e. at a time when it is not yet known whether the chapter will subsequently have a corresponding floating environment. So we first need an indicator for this. Since all entries are written via \addcontentsline
, the idea of generating this indicator within \addcontentsline
is obvious. As the indicator must be available in the next LaTeX run, it is written to the aux
file. The easiest way to do this is to generate a label:
\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}%
}{}%
}%
}
Here we use a generic LaTeX hook for the beginning of the \addcontentsline
command, which also receives all arguments of \addcontentsline
. The first argument is the file extension of the respective directory. Here we first test that it is not the table of contents itself and only then generate the indicator. Although this is not absolutely necessary, it does make sense.
We use a label as an indicator because in current LaTeX versions we can very easily test for its existence with \IfLabelExists:TF
and at the same time LaTeX automatically issues a message at the end of the LaTeX run in the event of changes, so that we know that another LaTeX run is necessary. The name of the label is simply made up of the chapter number and the file extension of the respective directory as well as some meaningful strings. We get the number of the chapter (in this first version) simply via \thechapter
.
However, as multiple defined labels lead to warnings, we use a second indicator to decide whether the label still needs to be defined or whether a label has already been created for the current chapter. To do this, we define another macro globally and only set the label if this macro has not yet been defined.
Next, we must ensure that the chapter entry is only written if the label for this chapter exists. To do this, we only need to set or delete the ToC feature chapteratlist
depending on whether the indicator label exists. We do not have to completely redefine \addchaptertocentry
for this either, but can use a generic LaTeX hook at the beginning of the command:
\AddToHook{cmd/addchaptertocentry/before}{%
\if@chaptertolists
\doforeachtocfile[float]{%
\IfLabelExistsTF{chapter@\thechapter @has@\@currext}{%
\setuptoc{\@currext}{chapteratlist}%
}{%
\unsettoc{\@currext}{chapteratlist}%
}%
}%
\fi
}
We use \if@chaptertolists
to check whether the chapteratlists
option is used at all. Strictly speaking, we could do without this test. We then check for each auxiliary file in the float
category whether the corresponding indicator label exists for the current chapter. If this is the case, we set the chapteratlist
feature for the corresponding file extension. If this is not the case, we delete the feature.
That was actually all. However, the use of \thechapter
has a decisive disadvantage. The whole thing does not work correctly if not only \chapter
but also \addchap
is used. Other unnumbered chapters, for example in the area of \frontmatter
or \backmatter
, also pose a problem. To solve the problem, we can use an absolute chapter counter abschapter
, which also counts unnumbered chapters. This can also be incremented using a generic hook for each \chapter
(and therefore also each \chapter*
and each \addchap
or \addchap*
). Then only \thechapter
needs to be replaced by \theabschapter
in the above definitions.
Here a complete example:
\documentclass[chapteratlists=entry]{scrbook}
% Code to limit chapteratlists=entry to chapters with float entries.
% → https://sf.net/p/koma-script/wiki-en/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}
Incidentally, the example still works if you load hyperref
, whereby it does not matter whether you load the package before or after the additional preamble code.