3

When working on a book I'd like to "ignore"(not compile) all chapters but the current one. I know there are methods to use like include and such BUT I do not want to use external files or some complex method.

I simply want to use \iffalse and fi(or something similar) BUT I want it transparent:

e.g.,

\ignorechapters{3,4} % <- Ignores all chapters **BUT** 3,4

and that is all that is needed so that only chapters 3 and 4 show up in the pdf.

So what is needed to do this? I imagine each \chapter macro will need to be modified in a robust way so that it will conditionally include the chapter or not

e.g., normally one has

\chapter[mc]{my chapter}
....
\chapter[mc2]{my chapter 2}
....
\chapter[mc3]{my chapter 3}

and I do this manually:

\chapter[mc]{my chapter}
\iffalse
....
\fi
\chapter[mc2]{my chapter 2}
\iffalse
....
\fi
\chapter[mc3]{my chapter 3}

and as you can see, it each \iffalse and \fi could easily be consumed into the \chapter macro without causing problems and done so transparently. (Assuming we can modify \chapter easily and not break it's original functionality)

--- Edit pseudo-code

newchapter macro
if previous chapter ignored  % Obviously if previous chapter doesn't exist this should be ignored
   insert `\fi`
end
if chapter ignored
   insert `\iffalse`
end
   insert `chapter data`
end macro

Hence the the newchapter macro will insert a \fi then an \iffalse into the stream if necessary.

We would also have to override the \end{document} to insert the final \fi if necessary(if the last chapter is to be ignored(which means it has an \iffalse and requires a \fi).

7
  • 2
    Why don't you want to use \include for your chapters? Sep 13, 2012 at 22:01
  • 1
    and then \includeonly keep-chapter-number-of-chapters-inserted-with-include
    – cmhughes
    Sep 13, 2012 at 22:03
  • Where does \ignorechapters get you that \includeonly|include get you besides the fact that the 'ignored' chapters are the ones that get included?
    – jon
    Sep 13, 2012 at 22:08
  • Are you concerned about inter-chapter references, since \iffalse...\fi would just ignore them and might cause undefined references?
    – Werner
    Sep 13, 2012 at 22:32
  • Why does everyone try to rewrite my question into asking about something else instead of just giving me a solution? As I said, I'm not interested in using \include and it's my business as to why I do not want to use external files... and that should be good enough! Sep 13, 2012 at 23:02

2 Answers 2

10

The following example implements the syntax described in the question. I have renamed \ignorechapters to \includechapters, because the chapters in the argument should be included, not ignored. Also I follow the convention of \includeonly: If \includechapters is not specified, all chapters are included. Otherwise the chapters are included that are specified. Starred chapters and chapters that are not followed by \iffalse are always included.

The normal syntax for \chapter is supported:

  • \chapter*{...}
  • \chapter{...}
  • \chapter[...]{...}

Excluded chapters

  • call \cleardoublepage,
  • increment their chapter number and
  • write an entry into the table of contents.

Package ltxcmds is only needed for a more robust \ltx@ifnextchar that also allows a conditional as next token.

\documentclass{book}
\usepackage{ltxcmds}

\makeatletter
\newcommand*{\includechapters}[1]{%
  \def\@includechapters{#1}%
}
\let\@includechapters\relax
\newcommand*{\org@chapter}{}
\let\org@chapter\chapter
\renewcommand*{\chapter}{%
  \@ifstar{\org@chapter*}{\chapter@aux}%
}
\newcommand*{\chapter@aux}{%
  \begingroup
  \@ifnextchar[{\chapter@aux@opt}{%
    \toks@{\org@chapter}%
    \let\chapter@tocentry\relax
    \chapter@@aux
  }%
}
\def\chapter@aux@opt[#1]{%
  \toks@{\org@chapter[{#1}]}%
  \def\chapter@tocentry{#1}%
  \chapter@@aux
}
\newcommand*{\chapter@@aux}[1]{%
  \toks@\expandafter{\the\toks@{#1}}%
  \ifx\chapter@tocentry\relax
    \def\chapter@tocentry{#1}%
  \fi
  \ltx@ifnextchar\iffalse{%
    \chapter@select
  }{%
    \expandafter\endgroup
    \the\toks@
  }%
}
\newcommand*{\chapter@select}[1]{%
  \ifx\@includechapters\relax
    \def\x{true}%
  \else
    \def\x{false}%
    \@for\ch:=\@includechapters\do{%
      \ifnum\ch=\numexpr\value{chapter}+1\relax
        \def\x{true}%
      \fi
    }%
  \fi
  \csname if\x\endcsname
  \else
    \cleardoublepage
    \refstepcounter{chapter}%
    \addcontentsline{toc}{chapter}{%
      \protect\numberline{\thechapter}%
      \chapter@tocentry
    }%
  \fi
  \expandafter\endgroup
  \csname if\x\expandafter\endcsname
  \the\toks@
}

\makeatother

\includechapters{2}

\begin{document}
\tableofcontents

\chapter[mc]{my chapter}
\iffalse
....
\fi
\chapter[mc2]{my chapter 2}
\iffalse 
....  
\fi  
\chapter[mc3]{my chapter 3}

\end{document}

The example includes the table of contents (starred chapter), excludes "my chapter", includes "my chapter 2", because it is listed in \includechapters, and includes "my chapter 3", because it is not followed by \iffalse.

Update: The method with \iffalse will not work, if the markup should be hidden inside \chapter without explicit markup for the end of chapter. When \iffalse is active, then TeX's fast scanning looks for conditional tokens only to find the matching \fi. Therefore a command token with the meaning of \fi that is not hidden inside macros is needed at any case.

Method via discarding pages

The following methods uses the property of chapters that they start and end at page breaks. If a chapter is ignored, then the chapter is typeset as usual, but the pages are discarded.

\documentclass{book}

\usepackage{atbegshi}

\makeatletter
\newcommand*{\includechapters}[1]{%
  \def\@includechapters{#1}%
}
\let\@includechapters\relax
\newcommand*{\org@chapter}{}
\newif\if@ignore@chapter
\renewcommand*{\@ignore@chaptertrue}{\global\let\if@ignore@chapter\iftrue}
\renewcommand*{\@ignore@chapterfalse}{\global\let\if@ignore@chapter\iffalse}
\AtBeginShipout{%
  \if@ignore@chapter
    \AtBeginShipoutDiscard
  \fi
}
\let\org@chapter\chapter
\renewcommand*{\chapter}{%
  \cleardoublepage
  \@ignore@chapterfalse
  \@ifstar{\org@chapter*}{\chapter@aux}%
}
\newcommand*{\chapter@aux}{%
  \begingroup
  \@ifnextchar[{\chapter@aux@opt}{%
    \toks@{\org@chapter}%
    \let\chapter@tocentry\relax
    \chapter@@aux
  }%
}
\def\chapter@aux@opt[#1]{%
  \toks@{\org@chapter[{#1}]}%
  \def\chapter@tocentry{#1}%
  \chapter@@aux
}
\newcommand*{\chapter@@aux}[1]{%
  \toks@\expandafter{\the\toks@{#1}}%
  \ifx\chapter@tocentry\relax
    \def\chapter@tocentry{#1}%
  \fi
  \ifx\@includechapters\relax
    \@ignore@chapterfalse
  \else
    \@ignore@chaptertrue
    \@for\ch:=\@includechapters\do{%
      \ifnum\ch=\numexpr\value{chapter}+1\relax
        \@ignore@chapterfalse
      \fi
    }%
  \fi
  \expandafter\endgroup\the\toks@
}
\makeatother

\includechapters{2}

\begin{document}
\tableofcontents

\chapter[mc]{my chapter}
....\the\currentgrouplevel
\chapter[mc2]{my chapter 2}
....
\chapter[mc3]{my chapter 3}

\end{document}

Now only the pages of the table of contents and chapter "my chapter 2" are included.

12
  • I think this is on the right track but you misinterpreted my question slightly. I do not want to have to explicitly use \iffalse and \fi. I want it to be automatically inserted. What you have will work so I have marked it as correct but please try and fix it. Sep 14, 2012 at 2:04
  • your example should look like \chapter[mc]{my chapter} .... \chapter[mc2]{my chapter 2} .... \chapter[mc3]{my chapter 3} at the bottom. Sep 14, 2012 at 2:06
  • (Note that the behavior you have of your example is correct but instead of inserting the \iffalse and \fi's you delete them) Sep 14, 2012 at 2:07
  • That's not possible. The \fi must be visible somehow, otherwise all would be ignored including \end{document} if a chapter is skipped. Even with the comment package you need a markup for the end of chapter that cannot be hidden inside macros. Sep 14, 2012 at 2:38
  • huh? It definitely is possible. Your macro must be logical enough to realize it is the last chapter! (the same type of logic must prevent a \fi from the first chapter. I'll ammend my questio with some pseudo code. Sep 14, 2012 at 2:51
3

You could load the comment package and surround the temporarily unwanted chapters with \begin{comment} and \end{comment} instructions. Note that these instructions must be on lines by themselves, with no leading blank (space) characters preceding them on the line.

1
  • You can also add various names for comments, e.g. \includecomment{chapter1} and surround the first chapter by \begin{chapter1} and \end{chapter1}. (You can find more details in the comment package documentation.)
    – Martin
    Sep 14, 2012 at 4:31

You must log in to answer this question.

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