18

In continuation of this question, I tried to make a list of items each consisting of unbreakable text. This can be done manually using minipage:

\documentclass[10pt,a4paper]{article}
\usepackage{lipsum} %for example
\setlength{\textheight}{7cm} %about one item fits per page
\begin{document}
\begin{itemize}
\item\begin{minipage}[t]{\linewidth}
\lipsum[1]
\end{minipage}
\item\begin{minipage}[t]{\linewidth}
\lipsum[2]
\end{minipage}
\end{itemize}
\end{document}

What I would like it to to define a list environment that is just like itemize (or whatever) only that the items are automatically inserted into a minipage as in my manual example. The solution should be robust for nested list environments, so if \item is to be redifined, it has to be done so in a very gentle way...not sure how. After redefining the environment itemize-block (for example) the following code should compile and not break the text in each item across pages:

\begin{itemize-block}
\item
\lipsum[1]
\item \begin{itemize}
\item let us make sure it compiles even with 
\item a nested list...
\end{itemize}
\item
\lipsum[2]
\end{itemize-block}

This can surely be done...only I have no idea how.

3 Answers 3

11

This is how I would do it:

\newenvironment{block-itemize}{%
  \itemize
  \let\olditem\item
  \let\closepage\relax  
  \renewcommand\item[1][]{%
    \closepage\olditem[#1]\minipage[t]{\linewidth}%
    \let\closepage\endminipage
  }%
}{%
  \closepage
  \enditemize
}

Then you write

\begin{block-itemize}
\item \lipsum[1]
\item \lipsum[2]
\end{block-itemize}

And a short explanation: When it starts, the environment begins a regular \itemize and then saves the usual definition of \item into \olditem. Then \item is redefined so that: (1) it closes the “previous” minipage (2) it starts a regular item (using \olditem) and (3) it opens a new minipage. Of course, for the very first item there is no minipage to close, that's why \closepage is first defined as \relax (do nothing) but it is then redefined to \endminipage right after the first use of \item. The end of the environment simply closes both the last minipage and the itemize environment.

Note: Actually, I would use something like \my@olditem and \my@closepage and throw the whole definition into a style file so that I don't accidentally redefine commands from another package. But I wanted to keep the code above somewhat clean without all those @'s lying around.

9
  • Thanks! Nice solution. I had to adapt it a little since the minipages inhibit the inter-item spacing. But that wasn't very difficult, using an additional \def. Commented Oct 24, 2010 at 11:14
  • 3
    As a cheap solution, how about defining a new \Item (or something) instead of messing with the existing \item? Commented Oct 24, 2010 at 14:52
  • 1
    What should one do in order have the same trick but for 'description' item? Simple reusing this code cleans term formatting of description list items (outputs as [term], instead of boldify)
    – glaz666
    Commented Feb 1, 2012 at 10:27
  • 1
    When I tried to use the current code for a description-like environment TeX Live complained about Illegal parameter number in definition of \block-description. Ditching the redefinition of \item and defining a \myitem outside the newenvironment hacked it for the time being. I don't know enough to suggest a more elegant solution. That said, it does precisely what I needed it to. Thanks. Commented Aug 5, 2014 at 21:04
  • 1
    @Devin I posted it as a separate answer. Commented Sep 10, 2014 at 23:25
2

This is a response to a comment on Juan's answer.

It's a modified version of his suggestion that works with description environments.

% ==========================================================
% Adapted from TeX.StackExchange.com user Juan A. Navarro's
% solution for itemize as seen at
% https://tex.stackexchange.com/a/4493/327
% ----------------------------------------------------------
\newcommand\myitem[1][]{%
  \closepage\item[#1]\minipage[t]{\linewidth}%
  \let\closepage\endminipage%
  }
% ----------------------------------------------------------
\newenvironment{block-description}{%
  \description
  \let\olditem\item
  \let\closepage\relax  
  %\def\item[1][]{\myitem}[1]
}{%
  \closepage
  \enddescription
}

I don't like having the item definition live outside the environment like that, but the variations that I tried with it inside all failed and I don't know enough to fix it.

Application looks like

\begin{block-description}

\myitem[Week 1] Aug. 18--22 \\

  \begin{tabular}{lp{2.5cm}p{7.5cm}}
            & Reading & Topic and notes \\
    \hline
    Mon.    & & Intro; administriva; pretest\\
    Tue.    & \\
    Wed.    & 18.1--18.5 & Electrostatics; Coulombs law \\
    Thu.    & \multicolumn{1}{r}{\textbf{Activity day:}} & 
              sticky electrostatics  \\
    Fri.    &  & Electrostatic force and multiple
                 charges 
  \end{tabular}

\myitem[Week 2]  Another table for the next week 

\myitem[Week 3]  Yet another table for the third week 

\begin{block-description} 

Each week appears in its entirety on one page or the other never broken.


Here's a frill that came up today: to enable real footnotes in this context use something like

\NewDocumentCommand\myfootnotetext{o +m}{% One optional and one long mandatory argument
  \closepage% End the current item so that we are outside of
            % minipage context
  \IfNoValueTF{#1}
  {\footnotetext{#2}}
  {\footnotetext[#1]{#2}}% Call \footnotetext either with or
                         % without the optional argument
  \let\closepage\relax% Re-define \closepage so that the next
                      % \myitem won't break when it tries \closepage
}

which requires \usepackage{xparse}. Then you can issue \footnotemark inside an item and \myfootnotetext at the bottom of that item and the footnote will appear at the bottom of the page (modulo pathological cases when it can't be placed properly, of course).

0

I can't comment so I post it as a solution here.

To address the "Illegal parameter number in definition" simply replace the #1 with ##1. Due to the nested definition, ## will be translated to the desired #, see https://texfaq.org/FAQ-hash

For instance, I could make it work for the \part in the exam package:

\newenvironment{block-parts}{%
  \parts
  \let\myolditem\part
  \let\myclosepage\relax  
  \renewcommand\part[1][]{%
    \myclosepage\myolditem[##1]\minipage[t]{\linewidth}%
    \let\myclosepage\endminipage
  }%
}{%
  \myclosepage
  \endparts
}

This code ensures that questions and the answer space remain on the same page when using the parts environment.

You must log in to answer this question.

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