5

Background

Trying to determine whether a column break must be inserted on a two-column page. There are multiple sections on the page. Before the last section on the page, I want to insert a column break, but only if within the first column and only if there is sufficient space in the second column (i.e., without forcing a page break).

Problem

The following code illustrates the problem:

\starttext
    \startcolumns[n=2, balance=no]
    \startsection[title=Section1]
    \input knuth
    \stopsection
    \startsection[title=Section2]
    \input zapf
    \stopsection
    \column
    \startsection[title=Section3]
    \input knuth
    \stopsection

    \stopcolumns
\stoptext

The \column break should not be applied because section 3 is in the second column, which causes an undesired page break. To clarify, the condition to determine whether or not to break the column should be independent of the text itself. For example, something like:

\setuphead[chapter][
  before={\startcolumns[n=2, balance=no,]},
  after={\stopcolumns},
]

% If the section is the last section in the chapter
% *and* the section is not in the last column *and*
% inserting a column break does not cause pagination...
\setuphead[section][
  before={%
    \if_last_section{%
      \if_not_last_column{%
        \if_fits_in_last_column_without_pagination{\columnbreak}
      }
    }
  },
]

\starttext
  \startchapter
    \startsection[title=Section1]
    \input knuth
    \stopsection
    \startsection[title=Section2]
    \input zapf
    \stopsection
    \startsection[title=Section3]
    \input knuth
    \stopsection
  \stopchapter
\stoptext

Question

How do you force ConTeXt to insert a column break if a section is in the first column, but not if the section is in the second column?

Related

Very similar question for LaTeX:

Using LaTeX, the following code -- part of the document class -- helped dynamically determine whether or not a column break should be present:

\def\columnbreakunlesslast{%
  \docolaction{\typeout{in first column}\inlastfalse}%
              {\typeout{in middle column}\inlasttrue}%
              {\typeout{in last column}\inlasttrue}%
  \unless \ifinlast \columnbreak \fi
}

This allowed documents to be written such that manually inserting column breaks was not necessary.

  • \page and \page[disable] will accomplish it (of course, wherever you wish to force the page break). Either way, irrespective whether \column is applied. – doed Oct 8 '13 at 7:16
  • @doed: See this answer: tex.stackexchange.com/a/122474/2148 -- it uses \docolaction{\typeout{in first column} to determine whether the text is still in the first column. I'm looking for something like that. – Dave Jarvis Oct 8 '13 at 18:14
  • The content is user-generated. I don't necessarily know where the "last section" will be within the document. – Dave Jarvis Oct 8 '13 at 19:48
  • Yes Dave. I realized that. great question though. – doed Oct 8 '13 at 19:50
  • I'm wondering not only if that answer it's useful enough to deserve a vote. I can care less about the bounty points. Since the question expired for one, and secondly because I'd just like to know what would someone who is actively involved with ConTeXt would do. It would be good to find out what Hagen himself would do in this case. – doed Oct 16 '13 at 11:22
4

I will try to keep it simple. You have two options, the first one:


\columnbreak

The second option is to apply some glue with \vfil, it all depends the amount of stretchability or shrinkability, for more glue apply \vfill or \vfilll to the box. Make a vertical box with either \vtop or \vbox. The latter is recommended, for the simple fact that it could be stretched and shrink and stretched and shrink some more with \columnbreak or \vfill. Did I say that ConTeXt can expand more than LaTeX?

So in ConTeXt the code would look as follows:


\vfil
\vbox{%
\input tufte
}

\vfil
\vbox{%
\input knuth\columnbreak % or \vfill
}

Consider this for example.


\starttext

\setuppagenumbering[state=stop]
    \startcolumns[n=3, balance=no]

    \section[1]

\input knuth

\section[2]

    \input zapf

    \section[3]

\vfil
\vbox{%
\input knuth 

}

\stopcolumns

\stoptext 

enter image description here

Or better yet, this one.



\def\doed\par{%
\vfil
\vbox{%
\input tufte
}}

\starttext

\hyphenation{wh-e-at}
\hyphenation{me-r-ge}
\hyphenation{st-r-ong-ly}
\setuppagenumbering[state=stop]
    \startcolumns[n=3, balance=no]

\section[1]

\input knuth

\section[2]

\input zapf

\section[3]

\doed  %The first break is applied. 

\input zapf

\section[4]

\doed %The second one follows. 

\input zapf
\input knuth
    \stopcolumns
\stoptext

enter image description here enter image description here

Or column break after first column



\def\doed\par{%
\vfil
\vbox{%
\input tufte
}}


\starttext

\hyphenation{wh-e-at}
\hyphenation{me-r-ge}
\hyphenation{st-r-ong-ly}
\setuppagenumbering[state=stop]
    \startcolumns[n=3, balance=no]

\section[1]

\input knuth

\section[2]

\doed 

\dorecurse{3}{\input zapf}

\section[3]

\doed

\input zapf

\input zapf

\section[4]

\doed

\input zapf

\input zapf

\section[5]

\doed

\input knuth

    \stopcolumns
\stoptext

enter image description here

enter image description here

And here is with \columnbreak which accomplishes the same thing than \columnbreakunlesslast from LaTeX




\starttext

\setuppagenumbering[state=stop]
    \startcolumns[n=3, balance=no]

\section[1]

\input knuth

\columnbreak

\section[2]

\dorecurse{2}{\input zapf}

    \section[3]

\input tufte

\stopcolumns

\stoptext 

enter image description here

  • 1
    Does ConTeXt change the meaning of \vfill and \unpenalty? If it doesn't, \vfill\unpenalty is completely equivalent to \vfill, as there is no penalty \unpenalty can act on. – egreg Oct 18 '13 at 12:43
  • Indeed! Although equivalent is not doing a thing. It's the same as adding a \unskip when no \medskip is present. I'll edit it. – doed Oct 18 '13 at 13:52

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.