In some magazines you will find that the table of contents entries first show the page number followed by the article title, for example:
90 OLED TV as a gaming display
94 Outdoor cell phone with satellite function
98 Smartphones under 500 euros
102 Mid-range GPUs from AMD and Nvidia
The existing styles for ToC entries in KOMA-Script do not provide such formatting and cannot be reconfigured accordingly. However, the \DeclareTOCEntryStyle
command from the tocbasic
package can be used to define new styles in KOMA-Script. More information on the instruction and the arguments that can be used in it can be found in the documentation. Here is an example:
\documentclass{scrartcl}
\usepackage{mwe}
\makeatletter
% This instruction is for demonstration purposes only and generates dummy
% text.
\newcommand*{\gotopage}[1]{%
\@whilenum\c@page<#1 \do{\blindtext\par}%
}
\makeatother
\makeatletter
% Note: The known options toclevel, beforeskip, entryformat, pagenumberwidth
% work. With pagenumberwidth, however, there is a change, that the page number
% is at the front. The distance 1em after the page number is currently a
% static \quad in the code.
\DeclareTOCEntryStyle{ct}[{%First definition and initialization of options:
\DefineTOCEntryCommandOption{entryformat}%
{scr@tso@}{@entryformat}[1]{entry format}%
\DefineTOCEntryLengthOption{beforeskip}%
{scr@tso@}{@beforeskip}{vertical skip before the entry}%
\DefineTOCEntryLengthOption{pagenumberwidth}%
{scr@tso@}{@pagenumberwidth}{width of page number box}%
\expandafter\providecommand%
\csname scr@tso@#1@entryformat\endcsname[1]{\normalfont ##1}%
% or:
% \csname scr@tso@#1@entryformat\endcsname[1]{\normalfont\sffamily\bfseries ##1}%
\expandafter\providecommand\expandafter*%
\csname scr@tso@#1@beforeskip\endcsname{\glueexpr \z@ plus .2\p@\relax}%
% automatic determination of the numerical level from the name of the level
\@ifundefined{#1tocdepth}{%
\Ifstr{#1}{part}{\@namedef{#1tocdepth}{-1}}{%
\Ifstr{#1}{chapter}{\@namedef{#1tocdepth}{0}}{%
\Ifstr{#1}{section}{\@namedef{#1tocdepth}{1}}{%
\Ifstr{#1}{subsection}{\@namedef{#1tocdepth}{2}}{%
\Ifstr{#1}{subsubsection}{\@namedef{#1tocdepth}{3}}{%
\Ifstr{#1}{paragraph}{\@namedef{#1tocdepth}{4}}{%
\Ifstr{#1}{subparagraph}{\@namedef{#1tocdepth}{5}}{%
\Ifstr{#1}{figure}{\@namedef{#1tocdepth}{1}}{%
\Ifstr{#1}{table}{\@namedef{#1tocdepth}{1}}{%
\Ifstr{#1}{lstlisting}{\@namedef{#1tocdepth}{1}}{%
\expandafter\let\csname #1tocdepth\expandafter\endcsname
\csname #1numdepth\endcsname
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
}{}%
\@ifundefined{#1tocdepth}{%
\expandafter\let\csname #1tocdepth\expandafter\endcsname
\csname toclevel@#1\endcsname
}{}%
% automatic determination of the width for the page number depending
% on the parent level
\scr@ifundefinedorrelax{scr@tso@#1@pagenumberwidth}{%
\Ifstrstart{#1}{sub}{%
\scr@ifundefinedorrelax{scr@tso@\scr@dte@nosub{#1}@pagenumberwidth}{%
\@namedef{scr@tso@#1@pagenumberwidth}{\@pnumwidth}%
}{%
\expandafter\let
\csname scr@tso@#1@pagenumberwidth\expandafter\endcsname
\csname scr@tso@\scr@dte@nosub{#1}@pagenumberwidth\endcsname
}%
}{%
\@namedef{scr@tso@#1@pagenumberwidth}{\@pnumwidth}%
}%
}{}%
}]{% Following defines the output:
\renewcommand*{\numberline}[1]{}% All entries without section number!
\ifnum \c@tocdepth >\numexpr \@nameuse{#1tocdepth}-\@ne\relax
\addpenalty\@secpenalty
\addvspace{\@nameuse{scr@tso@#1@beforeskip}}%
\begingroup
\parindent \z@ \rightskip \z@
\parfillskip \z@ \@plus 1fil
\@nameuse{scr@tso@#1@entryformat}{%
\@hangfrom{%
\makebox[\@nameuse{scr@tso@#1@pagenumberwidth}][r]{##2}\quad
}%
##1\par
}%
\endgroup
\penalty\@highpenalty
\fi
}
\makeatother
\DeclareTOCStyleEntry[beforeskip=.5\baselineskip plus 2pt]{ct}{section}
\begin{document}
\tableofcontents
\newpage
\setcounter{page}{90}
\section{OLED TV as a gaming display}
\gotopage{94}
\section{Outdoor cell phone with satellite function}
\gotopage{98}
\section{Smartphones under 500 euros}
\gotopage{102}
\section{Mid-range GPUs from AMD and Nvidia}
\gotopage{103}
\end{document}
The first, mandatory argument of \DeclareTOCEntryStyle
is the name of the new entry style. In the example, the name ct
was chosen in reference to the computer magazine c't.
The second argument is optional and specifies the initialization code. This is executed when the instruction \DeclareTOCStyleEntry
or \DeclareTOCStyleEntries
is used. The argument #1
is then the name of the respective directory level, for example section
. The initialization shown here defines the options entryformat
, beforeskip
, pagenumberwidth
and entryformat
. The level
option is automatically defined for all styles. It also initializes values for the options and the macros and lengths behind them. The code for this is largely taken from the predefined styles in tocbasic
and documented in the KOMA script source file scrkernel-tocstyle.dtx
.
The third, again mandatory argument contains the code for the actual formatting of the directory entry. This is explained in more detail here:
\renewcommand*{\numberline}[1]{}% All entries without outline number!
First, the \numberline
command is redefined so that it discards its argument. This argument is normally the outline number of the directory entry. Since the entry style already shows the page number first, in my opinion the
additional display of the outline number would be rather confusing. It is therefore discarded.
\ifnum \c@tocdepth >\numexpr \@nameuse{#1tocdepth}-\@ne\relax
...
\fi
\c@tocdepth
is the LaTeX-internal definition of the counter tocdepth
. This tests whether tocdepth
is greater than or equal to the number in #1tocdepth
- this is \sectiontocdepth
, for example. Only if this is the case is output at all. This is ultimately the secret behind the tocdepth
counter.
\addpenalty\@secpenalty
This instruction influences the permission for a page break before the entry. The default value for \@secpenalty
in LaTeX is -300, which means that pagination is preferred here. An alternative here would be to use a setting that depends on the level or the previous level.
\addvspace{\@nameuse{scr@tso@#1@beforeskip}}%
A vertical spacing is inserted according to option beforeskip
, whereby \addvspace
does not work cumulatively, so that consecutive \addvspace
do not add up, but only the maximum value is retained.
\begingroup
\parindent \z@ \rightskip \z@
\parfillskip \z@ \@plus 1fil
\endgroup
The actual output, but above all the change to the paragraph indent and the fill width of the last line of the paragraph, takes place in a group. All changes therefore remain local to this group. The paragraph indent is set to 0, the last line of the paragraph can be any length.
\@nameuse{scr@tso@#1@entryformat}{%
...
}
The entry is formatted according to option entryformat
. The default setting for section
of the class scrartcl
is \normalfont\sffamily\bfseries
, i.e. sans serif and bold.
\@hangfrom{%
\makebox[\@nameuse{scr@tso@#1@pagenumberwidth}][r]{##2}\quad
}%
##1\par
The page number from ##2
is output right-aligned in a box of the width from option pagenumberwidth
. The text from argument ##1
is output hanging. Note: Strictly speaking, ##1
is the outline number and the text, whereby the outline number precedes the text as an argument of the \numberline
instruction. As this statement was defined above in such a way that it ignores its argument, the outline number is not output here.
\penalty\@highpenalty
A page break is initially prohibited here. But we remember that in the event of a further entry of this style, a page break would then be explicitly permitted again.
So it's not a big secret. If you want to start creating your own styles, I recommend studying the predefined styles from tocbasic.sty
again. You should start with the less complex styles dottedtocline
, undottedtocline
and largetocline
. The highly configurable styles tocline
and toctext
are then of interest to those who require many configuration options and do not shy away from correspondingly complex definitions.
It should also be mentioned that the use of tocbasic
is of course also possible with other classes. While the KOMA-Script classes load and use the package automatically, the package must be loaded explicitly when using a standard class, for example.
(Translated with help of DeepL.com standard version.)