4

Inspired by how to check in latex whether the table of content is empty or not before added to the document I would like to have a head, that links to the table of contents if the toc is not empty, and does not link to it if it is empty. In the following I present a code for that. However, the parameter \TableofcontentsIsPrinted is not changed from FALSE to TRUE as it should. If it is renewcommand-ed in the \tableofcontents-definition it works at least in the sense that the head only links to the toc if \tableofcontents has been used in the document - but as I said, I would like to have the code check whether the toc is empty or not. Any help here?

\documentclass[a4paper,10pt,twoside]{article}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage{fancyhdr}
\usepackage{ifthen}

\makeatletter

\newcommand{\TableofcontentsIsPrinted}{FALSE}
\newcommand{\printcontentsnameifnotalreadydone}{%
    \section*{\contentsname}%
    \renewcommand{\printcontentsnameifnotalreadydone}{}
    \renewcommand{\TableofcontentsIsPrinted}{TRUE} % Put in here, it does not work.
}
\AtBeginDocument{%
    \let\oldcontentsline\contentsline
    \renewcommand{\contentsline}{
        \printcontentsnameifnotalreadydone
        \oldcontentsline
    }
    \renewcommand{\tableofcontents}{%
        \@starttoc{toc}%
%       \renewcommand{\TableofcontentsIsPrinted}{TRUE} % Put in here, this works half-way.
    }
}

\newcommand{\remakehead}{
    \ifthenelse{ \equal{\TableofcontentsIsPrinted}{TRUE} }{
        \fancyhead[RO,LE]{ \hyperref[sec:tableofcontents]{ Page \thepage } }
    }{
        \fancyhead[RO,LE]{ Page \thepage }
    }
}

\makeatother

\begin{document}
\pagestyle{fancy}

\begin{center} \Huge Heading \end{center}

\phantomsection
\tableofcontents
\label{sec:tableofcontents}
\remakehead

\newpage

\section{First Section}

\newpage

\section{Second Section}

\newpage

\end{document}
  • the main reason it does not work is that \renewcommand{\TableofcontentsIsPrinted}{TRUE} should be "global". – user4686 Apr 4 '14 at 20:06
3

As using TeX's conditionals defined with \newif is sometimes counter-intuitive and needs a somewhat extended apprenticeship, this update uses the etoolbox provided facilities \newbool, \setbool and \ifbool (or also \newtoggle, \settoggle, \iftoggle). There is no need then for package ifthen which the earlier version had used (with a boolean rather than a string comparison test) to minimally change the OP's MWE. Looking at the etoolbox documentation is recommended.

The redefinition of \contentsline has the effect that as soon as the new version is used it redefines itself to be its old self. Thus the added code (which displays the TOC title) is executed only once and additionally it sets a boolean (or toggle) to true (newly created conditionals are initially false). This is the flag which \remakehead tests to decide how to configure the header. This flag has to be set globally, as the .toc file will be executed within a group (this group is created via the action of the (unmodified) \@starttoc from the LaTeX2e kernel).

\documentclass[a4paper,10pt,twoside]{article}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage{fancyhdr}
\usepackage{etoolbox}

\makeatletter

\newbool {TableofcontentsIsPrinted}
% or
%\newtoggle {TableofcontentsIsPrinted}

\AtBeginDocument{%
    \let\oldcontentsline\contentsline
    \renewcommand{\contentsline}{%
        \section*{\contentsname}%
        \global\setbool{TableofcontentsIsPrinted}{true}%
        % or \global\settoggle{TableofcontentsIsPrinted}{true}%
        \let\contentsline\oldcontentsline
        \contentsline }
    \renewcommand{\tableofcontents}{\@starttoc{toc}}
}

\newcommand{\remakehead}{%
    \ifbool {TableofcontentsIsPrinted}
    % or \iftoggle {TableofcontentsIsPrinted}
    {\fancyhead[RO,LE]{\hyperref[sec:tableofcontents]{Click me to
          get to contents}}}
    {\fancyhead[RO,LE]{Page \thepage}}%
}

\makeatother

\begin{document}
\pagestyle{fancy}

\begin{center} \Huge Heading \end{center}

\phantomsection
\tableofcontents
\label{sec:tableofcontents}
\remakehead

\newpage

\section{First Section}

\newpage

\section{Second Section}

\newpage

\end{document}

Try this:

\documentclass[a4paper,10pt,twoside]{article}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage{fancyhdr}
\usepackage{ifthen}

\makeatletter

\newif\ifTableofcontentsIsPrinted

\AtBeginDocument{%
    \let\oldcontentsline\contentsline
    \renewcommand{\contentsline}{%
        \section*{\contentsname}%
        \global\TableofcontentsIsPrintedtrue
        \let\contentsline\oldcontentsline
        \contentsline }
    \renewcommand{\tableofcontents}{\@starttoc{toc}}
}

\newcommand{\remakehead}{%
    \ifthenelse{\boolean{TableofcontentsIsPrinted}}
    {\fancyhead[RO,LE]{\hyperref[sec:tableofcontents]{Click me to
          get to contents}}}
    {\fancyhead[RO,LE]{Page \thepage}}%
}

\makeatother

\begin{document}
\pagestyle{fancy}

\begin{center} \Huge Heading \end{center}

\phantomsection
\tableofcontents
\label{sec:tableofcontents}
\remakehead

\newpage

\section{First Section}

\newpage

\section{Second Section}

\newpage

\end{document}

whether empty

whether empty page 2

  • Thanks, the code works. Could you explain in a bit detail how your code works? I understand the \let command, but not how the code in \renewcommand{\contentsline}{ ... } works. Also, could you explain how this with the boolean/if-thingy \ifTableofcontentsIsPrinteddo works? I am asking, because I want to learn and not just copy-paste. – Make42 Apr 7 '14 at 8:44
  • TeX has a mechanism \newif\ifMyIf then \MyIftrue and \MyIffalse set it to true or false which then decides the branch taken \ifMyIf <true branch>\else<false branch>\fi. This original interface (see the TeXbook or TeX by topic) has many pitfalls though. I used it as you had ifthenelse loaded and were originally comparing strings which is less efficient, thus this was a minimal modification to preserve nevertheless your initial set-up. – user4686 Apr 7 '14 at 12:07
  • If you look at a .toc file you will see a bunch of \contentsline. The redefinition here will impact only the very first one: because at the end it redefines itself to be its old unmodified self. The added patch sets the boolean to be true. We need a \global because the TOC is typeset within a group. Then \remakehead tests the value of the boolean and takes accordingly the appropriate decision regarding the header. – user4686 Apr 7 '14 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.