2

I typeset a document where the color of the section headers changes periodically. I want to color the section entries in the toc as well matching with the colors of the corresponding sections.

To get this done I use \setkomafont{sectioning} and "inject" color commands in the toc. This does work as expected although I have the feeling that the latter is a kind of misuse of the toc entries. \setkomafont{sectionentry} and \setkomafont{sectionentrypagenumber} do not work as they color them all the same (as they are of course in the same section of the document).

The problem is: When I use hyperref, I get those Token not allowed in a PDF string warnings as these "incected" commands find their way into the table of contents of the PDF file. What is even more of a problem is that as hyperref redefines \contentsline the color of the page number is gone. \DeclareTOCStyleEntry does not help anyway because it does not know the number of the section which is needed to determine the correct color. It is needed nevertheless to get it right without hyperref.

Here is a MWE:

\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{blindtext}
\usepackage{arrayjobx}
\usepackage{pgf}
\usepackage{hyperref}

\colorlet{myblue}{blue!60!green!90!black}
\colorlet{myred}{red!80!black}
\colorlet{mygreen}{green!40!black}
\colorlet{default}{black}

\newarray\structurecolors
\readarray{structurecolors}{mygreen&myblue&myred}

\makeatletter
\newcommand{\structurecolor}[1][\value{section}]{%
  \pgfmathparse{int(mod(#1,\total@structurecolors) + 1)}%
  \checkstructurecolors(\pgfmathresult)%
  \color{\cachedata}%
  \ifnum#1=0%
    \color{black}
  \fi
}
\makeatother

\setkomafont{sectioning}{\sffamily\bfseries\structurecolor}

\renewcommand{\addsectiontocentry}[2]{%
  \IfArgIsEmpty{#1}{%
    \addtocentrydefault{section}{}{#2}
  }{%
    \addtocentrydefault{section}{\structurecolor[#1]#1}{\protect\structurecolor[#1]#2}
  }
}

\DeclareTOCStyleEntry[pagenumberformat={\sffamily\bfseries}]{default}{section}


\begin{document}
  \tableofcontents
  \Blinddocument
  \Blinddocument
\end{document}

I should mention that using the tocloft package is only the last resort as koma-script deprecates the use of tocloft.

Uncomment \usepackage{hyperref} to see the desired output. Thanks for any help or suggestions.

2 Answers 2

2

well the "token not allowed" can be avoid like always with \texorpdfstring, e.g. something like \texorpdfstring{\protect\structurecolor[#1]#2}{#2}. Regarding the color: you are relying on the text and the page number to be in the same group. But hyperref naturally has to add braces and grouping for the links. Store the color in some global variable and then repeat it in the page number:

\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{blindtext}
\usepackage{arrayjobx}
\usepackage{pgf}
\usepackage{hyperref}

\colorlet{myblue}{blue!60!green!90!black}
\colorlet{myred}{red!80!black}
\colorlet{mygreen}{green!40!black}
\colorlet{default}{black}

\newarray\structurecolors
\readarray{structurecolors}{mygreen&myblue&myred}

\makeatletter
\newcommand{\structurecolor}[1][\value{section}]{%
  \pgfmathparse{int(mod(#1,\total@structurecolors) + 1)}%
  \checkstructurecolors(\pgfmathresult)%
  \color{\cachedata}%
  \global\let\currentstructurecolor\cachedata
  \ifnum#1=0%
    \color{black}
  \fi
}
\makeatother

\setkomafont{sectioning}{\sffamily\bfseries\structurecolor}

\renewcommand{\addsectiontocentry}[2]{%
  \IfArgIsEmpty{#1}{%
    \addtocentrydefault{section}{}{#2}
  }{%
    \addtocentrydefault{section}{\structurecolor[#1]#1}{\texorpdfstring{\protect\structurecolor[#1]#2}{#2}}
  }
}


\DeclareTOCStyleEntry[pagenumberformat={\sffamily\bfseries\color{\currentstructurecolor}}]{default}{section}


\begin{document}
\showoutput
  \tableofcontents
  \section{a}
  \section{b}
 % \Blinddocument
 % \Blinddocument
\end{document}

enter image description here

1
  • Thank you. Meanwhile I found another solution in the documentation of tocloft. I'll post it as an alternative answer so anybody can see what fits best.
    – complanar
    Commented Feb 8 at 15:14
1

If you use \addtocontents{toc}{} inside of \renewcommand{\addsectiontocentry}{...} it does not affect the pdf toc in any way. Then you do not need to call \structurecolor[#1] inside of \addtocentrydefault. Use \begingroup ... \endgroup to make the changes local. This way even \DeclareTOCStyleEntry is not needed anymore.

\renewcommand{\addsectiontocentry}[2]{%
  \IfArgIsEmpty{#1}{%
    \addtocentrydefault{section}{}{#2}
  }{%
    \addtocontents{toc}{\begingroup\structurecolor[#1]}
    \addtocentrydefault{section}{#1}{#2}
    \addtocontents{toc}{\endgroup}
  }
}

Full MWE:

\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{blindtext}
\usepackage{arrayjobx}
\usepackage{pgf}
\usepackage{hyperref}

\colorlet{myblue}{blue!60!green!90!black}
\colorlet{myred}{red!80!black}
\colorlet{mygreen}{green!40!black}
\colorlet{default}{black}

\newarray\structurecolors
\readarray{structurecolors}{mygreen&myblue&myred}

\makeatletter
\newcommand{\structurecolor}[1][\value{section}]{%
  \pgfmathparse{int(mod(#1,\total@structurecolors) + 1)}%
  \checkstructurecolors(\pgfmathresult)%
  \color{\cachedata}%
  \ifnum#1=0%
    \color{black}
  \fi
}
\makeatother

\setkomafont{sectioning}{\sffamily\bfseries\structurecolor}
\setkomafont{sectionentry}{\sffamily\bfseries}

\renewcommand{\addsectiontocentry}[2]{%
  \IfArgIsEmpty{#1}{%
    \addtocentrydefault{section}{}{#2}
  }{%
    \addtocontents{toc}{\begingroup\structurecolor[#1]}
    \addtocentrydefault{section}{#1}{#2}
    \addtocontents{toc}{\endgroup}
  }
}

\begin{document}
  \tableofcontents
  \section{a}
  \section{b}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .