4

I've been trying to typeset my ToC like the one in the question How to make the ToCs part entry in onecolumn while the others are in two columns however, I don't have parts and therefore I want the chapters to be one-column while the {sub}*sections are in twocolumn mode.

My approach:

\documentclass{scrbook}

\usepackage{tocloft}
\usepackage{etoolbox}
\usepackage{multicol}

\pretocmd{\chapter}{\protect{\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\end{multicols}}\fi}}{}{}
\apptocmd{\chapter}{\protect{\addtocontents{toc}{\protect\begin{multicols}{2}}}}{}{}

\AtEndDocument{\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\end{multicols}}\fi}

\begin{document}

\tableofcontents

\chapter{FOO}
\section{bar1}
\section{bar2}
\section{bar3}
\section{bar4}

\chapter{BAR}
\section{foo1}
\section{foo2}
\section{foo3}
\section{foo4}
\end{document}

However, this is not working properly: The Chapter name disappears.

  • Is the approach fundamentally flawed or am I using \pretocmd and \apptocmd wrong?
  • Which approach would you use to solve this problem?
elemakil
  • 1,319

1 Answers1

4

Why does the your transformation of How to make the TOC's part entry in one column while the others in two columns? not work? That's because of the way \part and \chapter work. They don't capture the arguments themselves, but instead calls other helper macros to do that. As such, inserting elements "at the end of the \chapter command" actually interfere with the other parts of the macros.

Here's how you need to patch it instead:

enter image description here

\documentclass{scrbook}

\usepackage{tocloft,etoolbox,multicol}

\pretocmd{\chapter}{\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\end{multicols}}\fi}{}{}
\apptocmd{\chapterheadendvskip}{\addtocontents{toc}{\protect\begin{multicols}{2}}}{}{}
\AtEndDocument{\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\end{multicols}}\fi}

\begin{document}

\tableofcontents

\chapter{FOO}
\section{bar1}
\section{bar2}
\section{bar3}
\section{bar4}

\chapter{BAR}
\section{foo1}
\section{foo2}
\section{foo3}
\section{foo4}
\end{document}

\chapterheadendvskip is the last macro executed by but \chapter and \chapter* (actually \@@makechapterhead and \@@makeschapterhead) after the heading is set. It's the appropriate place to insert the multicols environment in the ToC.


If you're using a sectional package like titlesec, the above patch doesn't work. The reason is obvious - sectional packages typically redefine the way the sectional macros work, making the \patchcmd fail (either because of a changed command, or because the change is never seen due to the package suggesting a different route through the sectional unit construction). Here's one work-around when using titlesec - use the "after code" section to insert the \begin{multicol}{2} in the ToC:

\documentclass{scrbook}

\usepackage{multicol,etoolbox}
\usepackage{titletoc,titlesec}
\usepackage{hyperref}

\usepackage{xcolor}
\definecolor{myred}{RGB}{127,0,0}
\definecolor{myyellow}{RGB}{169,121,69}
\definecolor{gray75}{gray}{0.75}

\titleformat{\chapter}% Command
  [block]% Shape
  {\Huge\bfseries\color{myred}}% Format
  {\centering\protect{\color{myyellow}\thechapter\hfil}}% Label
  {1em}% Sep
  {}% Before-Code
  [\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\begin{multicols}{2}}\fi]% After-Code

\pretocmd{\chapter}{\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\end{multicols}}\fi}{}{}
\AtEndDocument{\ifnum\value{chapter}>0 \addtocontents{toc}{\protect\end{multicols}}\fi}

\begin{document}

\tableofcontents

\chapter{FOO}
\section{bar1}
\section{bar2}
\section{bar3}
\section{bar4}

\chapter{BAR}
\section{foo1}
\section{foo2}
\section{foo3}
\section{foo4}

\end{document}
Werner
  • 603,163
  • This is unexpected. I assumed that a command named apptocmd can actually append code to a command [meaning that appended code is executed after the original command has fully finished]. Your solution does work as advertised, however, my actual use case is much more involved using several other packages (hyperref, titletoc to name a few which I expect to modify the \chapter command). Is there a fail-safe approach to find the last command executed by \chapter (i.e. the one which needs to be patched)? It appears that patching \chapterheadendvskip in my non-MWE example has no effect: [1/2] – elemakil Sep 02 '14 at 22:52
  • The Master.toc file contains the ToC entries and the \end{multicols} forms but not the \begin{multicols}{2} forms. [2/2] – elemakil Sep 02 '14 at 22:53
  • @elemakil: Two things; (1) Post an example that replicates the problem; (2) \apptocmd does exactly what you say, but when executing \chapter{<chapter name>} the macro \chapter doesn't actually grab the argument {<chapter name>}. That's done by another macro. That's why you appendage to the command \chapter isn't actually correct. One would have to follow the trail of how the macros expand in order to find the correct/appropriate location for the insertion. Mine led me to \chapterheadendvskip. – Werner Sep 02 '14 at 23:24
  • You can find an updated example here. Could you explain what's the best way to "follow the trail" in order to find the command appropriate for patching? I think understanding how to solve this problem is much more important than the actual solution (not that I'd complain about being given the solution ;-) ). – elemakil Sep 03 '14 at 09:13
  • @elemakil: The reason why my solution doesn't work is because you're actually using a sectional package (titlesec in this case) which overwrites many of the sectional commands and how they interact with one another. Are you someone who enjoys debugging code? :) I'll update my code to accommodate the interaction with titlesec. – Werner Sep 04 '14 at 15:51
  • @elemakil: Note that using titlesec in conjunction with the KOMA-script classes is not recommended (check your .log for the warning message during compilation). Also, don't mix ToC-related packages like titletoc and tocloft. – Werner Sep 05 '14 at 19:08