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.
  • 2
    If you put the second block in a minipage, wouldn't the result be just the same? – Johannes_B Jun 19 '15 at 15:29
  • maybe something can be done using the needspace package. – barbara beeton Jun 19 '15 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 '15 at 16:00
  • @ChristianHupfer Yes that is right. – Trevor J Richards Jun 19 '15 at 19:12
  • What about the third block? What is meant to happen to that? – cfr Jun 20 '15 at 0:54
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.

  • 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 '15 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 '15 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 '15 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}
  • 1
    Possibly better: \setbox\TBox=\vbox{#1} and then just checking \ht\TBox. – egreg Jun 20 '15 at 15:21
  • Not really: \parbox sets the parindent to zero. With \vbox all settings are preserved. – egreg Jun 20 '15 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 '15 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.)

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.