10

I'm trying to generate a two-column task list with status information in the second column. It has to allow page breaks and should look more a less like this:

enter image description here

I managed to hack something together using tabu and enumitem but it's a bit a mess and the spacing is odd. Originally, there was too much space between the tasks (I added the negative vspace) and the status was originally supposed to be top-aligned (same height as the task title; I added the m qualifier for the first column). Ideally, it would just be one list with title, task text and status.

Any suggestions?

\documentclass{book}
\usepackage{lipsum}
\usepackage{enumitem}
\usepackage{longtable}
\usepackage{tabu}

\newcommand{\status}[1]{\fbox{\textsc{#1}}}
\newlist{task}{description}{1}
\setlist[task]{style=nextline, leftmargin=*, labelindent=*, itemindent=*, itemsep=0pt, topsep=2mm, partopsep=0mm}

\begin{document}
\lipsum[11]
\begin{longtabu} to\linewidth {@{}X[-5 j m]X[c p]@{}}
    \begin{task}
    \item[First Task] 
        \lipsum[13]
    \vspace{-3mm}
  \end{task}&
  \status{done}\\
  \begin{task}
      \item[Second Task] 
        \lipsum[4]
    \vspace{-3mm}
     \end{task}& 
     \status{in progress} \\
  \begin{task}
      \item[Third Task]
        \lipsum[10]
     \vspace{-3mm}
     \end{task} &
     \status{new} \\
\end{longtabu}
\end{document}
David Carlisle
  • 757,742
user21511
  • 178

4 Answers4

8

As you wish to have the status aligned at the top, I suggest you put it in to the label of the item. The following increases the right margin of the list by a definable length \statuswidth and places a box centered in that column with the status:

\documentclass{book}

\usepackage{lipsum}
\usepackage{enumitem}

\newlength{\statuswidth}
\setlength{\statuswidth}{3cm}
\newcommand{\status}[1]{\hfill\hbox to 0pt{\hbox to
\statuswidth{\hss\fbox{\textnormal{\scshape #1}}\hss}\hss}}

\newlist{task}{description}{1}
\setlist[task]{style=nextline, leftmargin=*, labelindent=*,
  itemindent=*, itemsep=0pt, topsep=2mm, partopsep=0mm,
  before=\setlength{\rightmargin}{\statuswidth}}

\begin{document}

\lipsum[11]
\begin{task}
\item[First Task\status{done}] 
  \lipsum[13]
\item[Second Task\status{in progress}] 
  \lipsum[4]
\end{task}

\end{document}

Sample output

If you wish to have the status flush right, then use the following definition of \status instead:

\newcommand{\status}[1]{\hfill\hbox to 0pt{\hbox to
\statuswidth{\hss\fbox{\textnormal{\scshape #1}}}\hss}}

i.e. the previous code with the penultimate \hss removed.

Andrew Swann
  • 95,762
  • Thanks a lot! I quite like this solution but there are overfull hboxes around the status. Do you know why? – user21511 Oct 30 '12 at 08:09
  • Thanks for pointing that out. I have now corrected the code. The original made an \hbox of width 0pt that contained a box of width \statuswidth. I had forgotten to hide the width of that inner box. – Andrew Swann Oct 30 '12 at 09:35
4

I'm inclined to a simpler approach:

\documentclass{book}
\usepackage{lipsum}
\usepackage{longtable}
\usepackage{calc,array}
\usepackage[pass,showframe]{geometry}

\newcommand{\status}[1]{\fbox{\textsc{#1}}}
\newcommand{\task}[1]{\multicolumn{2}{@{}l}{\textbf{#1}}}

\newlength{\statuslen}
\settowidth{\statuslen}{\fbox{\textsc{in progress}}}

\begin{document}
\lipsum[11]
\begin{longtable}
  {@{}>{\hspace*{3em}}l@{}
   m{\textwidth-2\tabcolsep-\statuslen-3em}
   l@{}}
\task{First Task} \\*
  &\lipsum[13]
  &\status{done} \\
\task{Second Task} \\*
  &\lipsum[4]
  &\status{in progress} \\
\task{Third Task} \\*
  &\lipsum[10]
  &\status{new} \\
\end{longtable}
\end{document}

enter image description here

The geometry package is used only to frame the page and show the margins.

David Carlisle
  • 757,742
egreg
  • 1,121,712
3

Another approach would be to just define your own custom environment. So, with the defintion of Task below you would just use

\begin{Task}{<name>}{status}
    text of task
\end{Task}

enter image description here

Code:

\documentclass{book}

\newcommand*{\TextA}{Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque scelerisque odio nec lorem dignissim ultricies. Quisque tristique turpis consectetur ligula bibendum vestibulum.}

\newcommand*{\TextB}{Aliquam tincidunt sapien vel odio consequat pulvinar. Donec laoreet cursus faucibus. Nam tincidunt malesuada arcu quis viverra. Vivamus eget quam ut justo mattis dignissim. Suspendisse convallis gravida consectetur. Nullam a nulla diam, in fringilla nulla. Sed at justo et lacus dapibus feugiat.}

\newcommand{\LeftMargin}{0.5cm}% \newcommand{\RightMargin}{2.5cm}% % http://tex.stackexchange.com/questions/588/how-can-i-change-the-margins-for-only-part-of-the-text \def\ChangeMargin#1#2{\list{}{\rightmargin#2\leftmargin#1}\item[]}% \let\endChangeMargin=\endlist%

\newcommand{\status}[1]{\fbox{\textsc{#1}}}

\newenvironment{Task}[2]{% \smallskip\par\noindent\textbf{#1}\hfill\status{#2}% \ChangeMargin{\LeftMargin}{\RightMargin}% \vspace{\dimexpr-\baselineskip+3pt\relax}% }{% \endChangeMargin\ignorespacesafterend% }

\begin{document} \noindent\TextB

\begin{Task}{First Task}{in progress} \TextA \end{Task} \begin{Task}{Second Task}{in progress} \TextB \end{Task} \begin{Task}{Third Task}{new} \TextA \end{Task} \end{document}

Peter Grill
  • 223,288
3

Another approach using a command \task with three arguments:

\task{<name>}{<status>}{<text>}

A complete example:

\documentclass{book}
\usepackage{lipsum}
\usepackage{tabu}
\usepackage{longtable}

\newcommand\status[1]{\fbox{\textsc{#1}}}
\newcommand\task[3]{%
  \multicolumn{2}{@{}p{6cm}}{\bfseries #1} & \status{#2} \\* & #3\\}

\begin{document}
\lipsum[11]
\begin{longtabu} to \linewidth{@{}p{1cm}@{}X[p]c@{}}
\task{First Task}{done}{\lipsum[2]} 
\task{Second Task}{in progress}{\lipsum[4]} 
\task{Third Task}{done}{\lipsum[2]} 
\end{longtabu}
\end{document}

enter image description here

Gonzalo Medina
  • 505,128
  • Interesting approach, thanks! Since title and content are split over two rows, it can lead to a page break in-between which isn't very nice. – user21511 Oct 30 '12 at 10:29
  • @user21511 the solution is simple; use \\* instead of just \\; I updated my answer with this modification. – Gonzalo Medina Oct 30 '12 at 12:46