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}

Peter Grill
  • 223,288
  • 3
    Several hours? You could \end{document} right after \tableofcontents and do something clever with pdfjam. – Sean Allred Jul 18 '15 at 20:28
  • It takes 2 runs to handle CHANGES in the toc. If nothing changes, 1 run will do. – John Kormylo Jul 18 '15 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. – Peter Grill Jul 18 '15 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. – Peter Grill Jul 18 '15 at 21:15
  • Interested to know what takes several hours. I have a 1000 page document with about 5000 images including 200+ tikz or pgfplot images and it takes minutes. Maybe you have just one rogue code segment? – Aubrey Blumsohn Jul 18 '15 at 21:40
  • 1
    @AubreyBlumsohn: It is not a normal text document, but an auto generated 1000+ page index. – Peter Grill Jul 19 '15 at 06:57
  • @PeterGrill I have updated my answer. – touhami Jul 20 '15 at 05:59

1 Answers1

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.
touhami
  • 19,520
  • Thanks. Will look into it in more detail tomorrow, but does seem to work on the test case. – Peter Grill Jul 20 '15 at 06: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. – Peter Grill Jul 20 '15 at 20:00
  • @PeterGrill I added some explanation, remember i don't use \foreach\x in {\value{page}... – touhami Jul 21 '15 at 21:10