# ConTeXt: avoid enumeration items across pages

If each \item is one or more paragraphs, sometimes ConTeXt will break these paragraphs across pages. In this specific case I would rather ConTeXt break between each item if a single paragraph or between paragraphs if multiple paragraphs. I've tried:

• loose. This changes the item group spacing sufficiently to sometimes, but not always, shift page breaks to between items.
• inbetween={\page[preference]}. This is too opportunistic and forces page breaks where none are needed. It also completely breaks the packed, nowhite and joinedup keywords especially when \setupwhitespace[big].
• \start...stoplinecorrection. This clearly isn't ideal when the item group is longer than a page.

Edit:

The excellent answer below raises so many interesting questions. I looked into the online wiki, the manual, and the excursion tutorial and couldn't find answers to these questions, below. If they are documented elsewhere just link to them here rather than repeating everything.

You define a new userdata environment with a specific alternative. I've seen that keyword used throughout ConTeXt and assumed that it was an enumeration specific to each individual macro, i.e. every enumeration value would trigger behaviour hardcoded into the macro definition. But here you define a completely new alternative. What does that mean? At what stage is the alternative used or called? What is its scope; what does it do?

In the alternative you override the 'renderingsetup keyword. Similar question regarding this. I assume it affects the new userdata environment before page rendering starts. Why must you use an alternative to override 'renderingsetup'?

In the setups you define a new box and contents. Why do you disable the following blank?

Then you test the height of the box. I'd ask how this is possible before rendering, i.e. in renderingsetup, but that's more of a TeX question, so nevermind.

If the height of the box is smaller than \textheight you just insert the box (with contents). Is it a good idea to unbox if the height is less than \pagegoal?

Otherwise, for clarification on longer items: An item is composed of several paragraphs. Right now only paragraphs, but in the future maybe a nested item list or two. I only want pagebreaks between paragraphs with two exceptions:

• Never page break after the first paragraph, as it is somewhat of a heading.
• Only break a paragraph (into pieces) if it is longer than 0.25\textheight, but your answer already demonstrates how to do this.

But that seems pretty advanced. Should I make it a new question, to demonstrate for loop with index, introspection (is item at index a paragraph vs glue?), etc?

• I think that it is better to break up your questions into related bits and ask them separately. The current question asks too many things, which does not work well in the format of this site. Dec 4, 2018 at 13:57
• I think I'm about to take this a little far. Dec 5, 2018 at 20:34

There is no predefined option for itemize which can help here because the entries don’t on which page they begin and end.

A simple method to keep the content of a entry together on a single page is to put everything in a box, which prevents a page between in it.

In the example below I use the userdata environment to store the content of each item in a buffer which I put afterwards in a \vbox. This method isn’t perfect because many conditionals for itemize don’t work anymore and I have to use \blank[disable] to get rid of the empty line which is inserted at them begin of each item.

\defineuserdataalternative
[itemize]
[renderingsetup=userdata:itemize]

% \startsetups [userdata:itemize]
%   \setbox\scratchbox\vbox {
%     \blank[disable]
%     \startitem
%       \getinlineuserdata
%     \stopitem
%   }
%   \ifdim\ht\scratchbox>\textheight
%     \page\unvbox\scratchbox
%   \else
%     \box\scratchbox
%   \fi
% \stopsetups

\startsetups [userdata:itemize]
\vbox {
\blank[disable]
\startitem
\getinlineuserdata
\stopitem
}
\stopsetups

\defineuserdata [item] [alternative=itemize]

\setuppapersize [A5]

\starttext

\startitemize
\startuserdata [item]
\samplefile{zapf}
\stopuserdata
\startuserdata [item]
\samplefile{ward}
\stopuserdata
\startuserdata [item]
\samplefile{tufte}
\stopuserdata
\startuserdata [item]
\samplefile{weisman}
\stopuserdata
\stopitemize

\stoptext


When your goal is only to keep the paragraphs in a entry together but you don’t mind to have a break between them you can use the \keeplinestogether command.

% \define\ItemizeCommand
%   {\keeplinestogether{20}}

\define\ItemizeCommand
{\EveryPar{\keeplinestogether{20}}}

\setupitemize
[command=\ItemizeCommand]

\setuppapersize [A5]

\starttext

\startitemize
\startitem
\samplefile{zapf}
\stopitem
\startitem
\samplefile{ward}
\stopitem
\startitem
\samplefile{tufte}
\stopitem
\startitem
\samplefile{weisman}
\stopitem
\stopitemize

\stoptext


• Why compare the height of box with textheight? Shouldn't this be compared with pagegoal or something similar. Dec 3, 2018 at 21:30
• The question doesn’t make clear what should happen when a item is longer than one page. Dec 3, 2018 at 21:40
• If I use this solution with \sym and write up the paragraph on a new line (i.e. \sym{>}\nThis is displayed on the same line as the symbol) then ConTeXt typesets this newline as additional horizontal whitespace between the symbol and the first line. This only occurs with \sym, and not with \item, \start...stopitem, or \head, and only with using an \EveryPar command. Any ideas? Dec 17, 2018 at 19:27
• I replaced command= with inner=` and it seems to work fine. Dec 17, 2018 at 19:55