[Tex/LaTex] Optional newpage command

macrospage-breaking

Does there exist a command (which I will call \newpageoptional) which acts in the following way:

    Text and code 1

    \newpageoptional{
    Text and code 2
    }

    Text and code 3

The effect should be:

  1. If "Text and code 2" can fit on the current page, no effect.
  2. If "Text and code 2" cannot fit on the current page, then all of "Text and code 2" is moved to the next page.

Best Answer

It’s a bit sad to see how easily people are inclined to forget the good ol’ ways of doing things… Seriously, this question (like others I have already seen on TeX.SX) looks like a classical problem which is discussed, and solved, on page 111 of The TeXbook, where the \filbreak command is introduced. Quoting from there:

The most interesting macro that plain TeX provides for page make-up is called \filbreak. It means, roughly, “Break the page here and fill the bottom with blank space, unless there is room for more copy that is itself followed by \filbreak.” Thus if you put \filbreak at the end of every paragraph, and if your paragraphs aren’t too long, every page break will occur between paragraphs, and TeX will fit as many paragraphs as possible on each page. The precise meaning of \filbreak is

\vfil\penalty-200\vfilneg

according to Appendix B; and this simple combination of TeX’s primitives produces the desired result…

The \filbreak macro is defined in LaTeX too (in ltplain.dtx), and the definition is exactly the same as that of Appendix B of The TeXbook:

\def\filbreak{\par\vfil\penalty-200\vfilneg}

So you could just use it in your documents, without loading any package:

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{lipsum}

\begin{document}

\lipsum[1]\filbreak
\lipsum[2]\filbreak
\lipsum[3]\filbreak
\lipsum[4]\filbreak
\lipsum[5]\filbreak
\lipsum[6]\filbreak
\lipsum[7]\filbreak
\lipsum[8]\filbreak

\end{document}

This works as expected; but one might object that it requires typing \filbreak at the end of every paragraph. Well, of course this can be made automatic:

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{lipsum}

\makeatletter
\def\filbreak{\@@par\vfil\penalty-200\vfilneg}
\makeatother

\begin{document}
\begingroup
    \let\par\filbreak
    \lipsum[1-32]
\endgroup
\end{document}

Obviously, it is necessary to redefine \filbreak to invoke \@@par, instead of \par, to avoid infinite recursion.

Related Question