3

I have a working, fairly complex setup to create a large-ish document (> 200 pages). I would like to create a "preview" of selected parts of the document. There are numerous questions about how to cut and splice the PDF file - this is not what I'm asking for.

What I would like to do is

  • mark the areas in the document source that I would like to have included in the excerpt - I'm thinking about some kind of \startpreview and \endpreview commands
  • write the pages that these commands would be rendered to if they were text to some external file (or possibly the .aux file if that helps or is easier?) so that I get the page ranges to extract dynamically
  • assemble either a command line script or some .tex file that extracts the actual preview

I should be able to get the last step together, but I get the feeling that there should be a package or some pre-assembled tool to achieve the first two steps. I haven't been able to find anything. What would be the best way to get the page ranges of the marked areas in the document out into some post-processing tool?

  • The atbegshi package allows you to discard some pages from the output file. With a little programming one could select which pages stay in the final file and discard the rest. Is this what you are looking for? – Phelype Oleinik Mar 2 '18 at 21:12
  • I'm looking for a way to mark and identify the pages in the first place. I will have to do some post-processing anyway - resizing, watermarking and so on - so having a secondary run would not be an issue. That being said - combining atbegshi with some kind of toggle might work... Just needs a bit of care, because I actually need to capture the page that contains the \endpreview command... – vwegert Mar 2 '18 at 21:30
4

I'm adding another answer because the previous one almost works and because it is a completely different approach.

I defined the same two commands; \startpreview and \endpreview.

Their behavior:

The \startpreview macro defines a \prevpage macro that holds the current page number. The \endpreview macro will complete this page range crating a macro with start-end.

The \startpreview macro will write this page range to a file \jobname.prev.

At the end of the compilation, the file \jobname.prev will have the page ranges of the "preview". To create the preview pdf one just have to pass this file to a pdf manager software, like pdftk.

For example, with pdftk and bash, the preview pdf could be created with:

pdftk main.pdf cat $(cat main.prev) output preview.pdf

The code:

\documentclass{article}

\usepackage{lipsum}
\usepackage{atbegshi}
\newcounter{globalpage}
\AtBeginDocument{\setcounter{globalpage}{1}}
\AtBeginShipout{\stepcounter{globalpage}}

\newwrite\fid
\immediate\openout\fid=\jobname.prev
\newif\ifprev\prevfalse
\newif\ifstartprev\startprevfalse

\def\removelastpage#1-#2\null{%
  \xdef\prevpage{#1-}%
}
\def\startpreview{%
  \ifstartprev
    \errmessage{You must use \string\endpreview\space before using another \string\startpreview.}
  \fi%
  \startprevtrue%
  \ifprev% one page range was already defined
    \ifnum\lastpage=\the\value{globalpage}% if the last page of the previous range is equal to the first page of this range then they are the same
      \expandafter\removelastpage\prevpage\null%
    \else% otherwise, write
      \immediate\write\fid{\prevpage}%
      \xdef\prevpage{\the\value{globalpage}-}%
    \fi%
  \else%
    \xdef\prevpage{\the\value{globalpage}-}%
  \fi
  \prevfalse
}
\def\endpreview{%
  \ifstartprev\else
    \errmessage{You must use \string\startpreview\space before using \string\endpreview.}
  \fi%
  \startprevfalse%
  \xdef\prevpage{\prevpage\the\value{globalpage}}%
  \xdef\lastpage{\the\value{globalpage}}%
  \prevtrue%
}
\AtEndDocument{%
  \ifstartprev\endpreview\fi% finish preview if necessary
  \immediate\write\fid{\prevpage}%
}

\let\oldthepage\thepage
\renewcommand*\thepage{{\Huge\oldthepage}}
\begin{document}
\Huge

\startpreview
\lipsum[1]
\endpreview

\lipsum[2-5]

\startpreview
\lipsum[6]
\endpreview

\startpreview
\lipsum[7-8]
\endpreview

\end{document}

Update:

The previous version of the code saved \the\value{page} to the .prev file. In my naïvety I didn't see the problem in that, but once the code was to be used in, say, a book that contained a table of contents with roman numerals, the saved numbers would be wrong. So I defined a globalpage and made it increase with the \AtBeginShipout hook, so the number saved in the .prev file is, hopefully, the global page number.

4

Here it goes :)

I created two macros: \startpreview and \endpreview.

Their behavior:

  • Everything after a \startpreview will be written to the output pdf.

  • Everything starting from the page after an \endpreview will be discarded, unless a \startpreview overrides this.

How they work:

I defined two counters (I couldn't make it work with a \newif, for some reason), \thiskeep and \nextkeep. \thiskeep will tell if the current page is to be kept, and \nextkeep tells if the next one will be kept.

The \startpreview macro will set \thiskeep and \nextkeep to keep the current page and any one that comes after.

The \endpreview macro will set \nextkeep to discard the next page. But it will do nothing with \thiskeep. This is to make \startpreview "stronger" than \endpreview.

Finally, there is a hook when each page is shipped out that checks if \thiskeep is set to 1. If it is not, then the hook discards the page and make \thiskeep be \nextkeep.

The default behavior is to discard every page.

The code:

\documentclass{article}

\usepackage{lipsum}
\usepackage{atbegshi}

\newcount\thiskeep\global\thiskeep=0
\newcount\nextkeep\global\nextkeep=0

\def\startpreview{%
  \global\thiskeep=1%
  \global\nextkeep=1%
}
\def\endpreview{%
  \global\nextkeep=0%
}

\AtBeginShipout{%
\ifodd\thiskeep\else%
  \AtBeginShipoutDiscard%
\fi%
\global\thiskeep=\nextkeep%
}

\let\oldthepage\thepage
\renewcommand*\thepage{{\Huge\oldthepage}}
\begin{document}
\Huge

\startpreview
\lipsum[1]
\endpreview

\lipsum[2-5]

\startpreview
\lipsum[6]
\endpreview

\startpreview
\lipsum[7-8]
\endpreview

\end{document}

Output:

Furnishings added to make visualization easy.

Note the missing pages between 2 and 6 :)

enter image description here

  • While this solution looks brilliant, it has an undesired side-effect: it breaks all references to excluded pages. This includes the TOC which I definitely want to include, but since I'm also using fancyref, it completely breaks the build process :-(( – vwegert Mar 4 '18 at 13:54
  • @vwegert Ouch, I didn't realise that. I'll take a look, see if I can solve that. But I don't think that it will be so simple this time :/ – Phelype Oleinik Mar 5 '18 at 12:12
  • I'd be perfectly happy to get the page ranges written to a separate output file, if I only knew how to do that – vwegert Mar 5 '18 at 12:16
  • @vwegert See my new answer. I think it might suit your needs. – Phelype Oleinik Mar 5 '18 at 18:21

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.