6

I have a document that I need to recompile often. Currently I am doing the standard two pass compile where the first pass generates the .toc file and the second pass then inserts it.

However, as my document compilation takes several hours, and the second pass only changes the first few pages I am looking for a way to avoid recompiling the entire document just to generate the Table of Contents.

Notes:

  • I am not worried about other issues that are handled in the second pass such as labels, cross references, longtable, \tikzmark, etc.
  • I do need the bookmarks and the TOC to have links to the corresponding pages, but do not need any links back to the TOC itself.
  • The MWE below uses the solution from set minimum number of pages for TOC, to leave sufficient blank PDF pages for the Table of Contents. This should ensure that the bookmarks and links form the TOC to the body work properly.
  • This document is only for internal use so leaving a few extra blank pages in the TOC to allow for growth of the document is perfectly acceptable.

Code:

\def\NumberOfChapters{10}
\def\NumberOfSections{50}
\def\NumberOfPagesForTOC{14}

\documentclass{book}
\usepackage{lipsum}
\usepackage{pgffor}
\usepackage[colorlinks=true]{hyperref}

\begin{document}
\frontmatter
\pagenumbering{roman}
\tableofcontents
\cleardoublepage


%% https://tex.stackexchange.com/questions/43140/set-minimum-number-of-pages-for-toc
\foreach\x in {\value{page},...,\NumberOfPagesForTOC}{\vbox{}\newpage}% Insert up to absolute page #14.

\pagenumbering{arabic}

\mainmatter
\foreach \x in {1,...,\NumberOfChapters}{%
    \chapter{Chapter \x}
    \foreach \y in {1,...,\NumberOfSections}{%
        \section{Section \y}
        \lipsum[1-7]
    }
}
\end{document}
7
  • 3
    Several hours? You could \end{document} right after \tableofcontents and do something clever with pdfjam. Jul 18, 2015 at 20:28
  • It takes 2 runs to handle CHANGES in the toc. If nothing changes, 1 run will do. Jul 18, 2015 at 21:00
  • @SeanAllred: About 3-5 hours. It is an auto generated index. Yes, I was thing about using pdfpages but don't know how to ensure that the links from the TOC to the appropriate pages in the document will work. Jul 18, 2015 at 21:14
  • @JohnKormylo: No changes in TOC is a fine assumption. That is the point of leaving sufficient blank PDF pages such that there are no changes in the TOC as to what PDF page needs to be linked to. Jul 18, 2015 at 21:15
  • 1
    @AubreyBlumsohn: It is not a normal text document, but an auto generated 1000+ page index. Jul 19, 2015 at 6:57

1 Answer 1

2

Updated: My first solution was bad since the bookmark package works from the first pass. Here is another solution, this time with bookmarks and toc links

Suppose this the main.tex file

\def\NumberOfChapters{20}
\def\NumberOfSections{50}

\documentclass{book}
\usepackage{lipsum}
\usepackage{pgffor}


\usepackage[colorlinks=true]{hyperref}

\begin{document}
\frontmatter
\tableofcontents
\mainmatter
\foreach \x in {1,...,\NumberOfChapters}{%
    \chapter{Chapter \x}
    \section{Section \x}
    \lipsum[1-7]
    \foreach \y in {1,...,\NumberOfSections}{%
        \section{Section \y}
        \lipsum[1-3]
    }
}

\end{document}

We need a second maintocbook.tex file (2 pass)

\documentclass{book}

\usepackage{pdfpages}
\usepackage[colorlinks=true]{hyperref}

\def\mtpage{1}

\begin{document}
\frontmatter
\tableofcontents

\mainmatter

\begingroup
\makeatletter
\def\contentsline#1#2#3#4{%
\ifnum #3 = \mtpage\else
\includepdf[pages={\the\numexpr\mtpage+2\relax - \the\numexpr#3+1\relax}]{main.pdf}%
\gdef\mtpage{#3}%
\fi
\phantomsection
\addcontentsline{toc}{#1}{\@gobbletwo #2}%
}
\makeatother
\input{main.toc}
\endgroup

\includepdf[pages={\the\numexpr\mtpage+2\relax-}]{main.pdf}
\end{document}

Explanation:

\contentsline {chapter}{\numberline {1}Chapter 1}{1}{chapter.1}

\@gobbletwo >> \long\def \@gobbletwo #1#2{} --> defined in latex.ltx

so in our case

\@gobbletwo #2 = \@gobbletwo\numberline {1}Chapter 1 >> Chapter 1

main.toc

\contentsline {chapter}{\numberline {1}Chapter 1}{1}{chapter.1}
\contentsline {section}{\numberline {1.1}Section 1}{1}{section.1.1}
\contentsline {section}{\numberline {1.2}Section 1}{2}{section.1.2}
\contentsline {section}{\numberline {1.3}Section 2}{3}{section.1.3}

algorithm

1st \contentsline: #3=1=\mtpage we do 
\phantomsection
\addcontentsline{toc}{#1}{\@gobbletwo #2} => \addcontentsline{toc}{chapter}{Chapter 1}

2nd \contentsline: #3=1=\mtpage we do 
\phantomsection
\addcontentsline{toc}{#1}{\@gobbletwo #2} => \addcontentsline{toc}{section}{Section 1}

3rd \contentsline: #3=2>\mtpage we include all pages before the page number #3 
that's mean from \mtpage to #3-1
but since there is 2 pages (i, ii) in frontmatter (\tableofcontents) 
the page number 1 is 3rd page of the pdf and so on, 
that's why we use \mtpage+2 to #3+1. Next we set \mtpage=#3 and restar.
3
  • Thanks. Will look into it in more detail tomorrow, but does seem to work on the test case. Jul 20, 2015 at 6:51
  • Am having some difficulty adapting it for my needs. Can you add some explanation on the logic, especially the math on \mtpage and the \@gobbletwo. Jul 20, 2015 at 20:00
  • @PeterGrill I added some explanation, remember i don't use \foreach\x in {\value{page}...
    – touhami
    Jul 21, 2015 at 21:10

You must log in to answer this question.

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