4

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.
6
  • 2
    If you put the second block in a minipage, wouldn't the result be just the same?
    – Johannes_B
    Jun 19, 2015 at 15:29
  • maybe something can be done using the needspace package. Jun 19, 2015 at 15:34
  • I assume the second code block should be shifted completely and not be broken, if there is no space left?
    – user31729
    Jun 19, 2015 at 16:00
  • @ChristianHupfer Yes that is right. Jun 19, 2015 at 19:12
  • What about the third block? What is meant to happen to that?
    – cfr
    Jun 20, 2015 at 0:54

3 Answers 3

5

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.

3
  • 1
    \filbreak has the small defect of being difficult to turn off. There are several answers that mention it: tex.stackexchange.com/search?q=filbreak
    – egreg
    Jun 20, 2015 at 20:48
  • How would a \newpageoptional look? I mean, you are inserting \filbreak between every paragraph, what if you want only one paragraph? Just add \filbreak<paragraph>\filbreak?
    – Manuel
    Jun 21, 2015 at 10:46
  • @Manuel: It depends on what should happen to the following paragraphs: should they be moved unconditionally to the next page? This is probably what egreg refers to when he speaks of \filbreak “being difficult to turn off”.
    – GuM
    Jun 21, 2015 at 12:02
2
\documentclass[paper=A6]{scrartcl}
\usepackage{needspace}
\usepackage{blindtext}

\newsavebox\TBox
\newcommand\newpageoptional[1]{%
     \savebox\TBox{\parbox{\linewidth}{#1}}% to get the height of the text
     \needspace{\dimexpr\ht\TBox+\dp\TBox}%  totalheight
     #1}
\begin{document}

\blindtext

\newpageoptional{%
    Text and code 2 with blindtext
    \blindtext
}

       Text and code 3

\end{document}
3
  • 1
    Possibly better: \setbox\TBox=\vbox{#1} and then just checking \ht\TBox.
    – egreg
    Jun 20, 2015 at 15:21
  • Not really: \parbox sets the parindent to zero. With \vbox all settings are preserved.
    – egreg
    Jun 20, 2015 at 16:51
  • LaTeX uses \maxdepth=5pt. If you want to be fussy, check whether the depth is above 5pt and add the difference.
    – egreg
    Jun 20, 2015 at 16:56
1

Probably you want \raggedbottom which means that when there's no space for something in a page a new one is open without flushing the contents to align to the bottom. Plus a {minipage} environment (which doesn't break across pages). Just put \raggedbottom in the preamble and use

\newcommand\newpageoptional[1]
   {\par\noindent\xdef\svparindent{\the\parindent}%
    \begin{minipage}[t]{\linewidth}\parindent\svparindent
      #1\par\xdef\svprevdepth{\the\prevdepth}%
    \end{minipage}\par\prevdepth\svprevdepth}

(Info about all those extra commands around the minipage here.)

You must log in to answer this question.

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