# How can I synchronize page-breaking text across columns?

tl;dr: Like footnotes, but on the side (easy part). These notes must be on the same page as their reference points, so the "main text" needs to break whenever the notes break.

I'm trying to produce something like this:

I've been using memoir. Here's an idea I had. My understanding is that \footnote creates a float that tries to place itself at the bottom of the nearest page. Would it be possible to place the "footnote anchor" elsewhere? For example, with some interesting page geometry, something like this:

The difficult part is in the question title: ensuring that page breaks respect the column-column alignment.

Here is a MWE.

\documentclass{memoir}

% geometry stuff here

\begin{document}
Blind Text

Lorem ipsum dolor sit amet. \columnnote{This is the first footnote.''}

The quick brown fox jumped over the lazy dog. \columnnote{This is the second footnote.''}
\end{document}


This will write notes from top to bottom using the entire right column. Page breaking is done using the aux file and \everypar.

Needless to say, this approach will conflict with any package which uses \everypar (within the paracol environment).

\documentclass{memoir}
\usepackage{xcolor}
\usepackage{paracol}
\usepackage{lipsum}

\newcommand{\darkmark}[1]% #1 = text to write white on black background
{\rlap{\rule[-.2\baselineskip]{\bibindent}{\baselineskip}}%
\makebox[\bibindent]{\color{white}#1}}

% global registers

\newcounter{abortparagraph}% incremet for every aborted paragraph
\newcounter{columnnote}[chapter]
\globalcounter{columnnote}% synchronized across columns
\newlength{\columnheight}% space used for column notes
\newlength{\columnroom}% available space for column notes
\newif\ifparagraphaborted% ignore extra everypar after abort
\newcommand{\leftcolumnpage}{}% reserve global names
\newcommand{\rightcolumnpage}{}% for page synchronization

% move current paragraph to next page

\newcommand{\newabortparagraph}[1]% #1 = \theparagraph, #2 = \thepage
{\stepcounter{abortparagraph}%
\global\expandafter\def\csname abortparagraph\arabic{abortparagraph}\endcsname{#1}}

\makeatletter
\newcommand{\abortparagraph}% \everypar
{\ifparagraphaborted% ignore extra everypar after abort
\global\paragraphabortedfalse
\else
\global\edef\leftcolumnpage{\arabic{page}}%
\stepcounter{paragraph}%
\bgroup% in case \tempa and \tempb previously used
\@ifundefined{abortparagraph\arabic{abortparagraph}}{}%
{\edef\tempa{\csname abortparagraph\arabic{abortparagraph}\endcsname}%
\edef\tempb{\theparagraph}%
\ifx\tempa\tempb% compare strings
\strut\newpage
\stepcounter{abortparagraph}%
\global\paragraphabortedtrue
\fi}%
\egroup
\fi}

% synchronize pages

\newcommand{\columnnotepage}[2]% #1 = label, #2 = \thepage
{\global\expandafter\def\csname columnnotepage#1\endcsname{#2}}

% redefine paracol environment start

\let\oldparacol=\paracol

\renewcommand{\paracol}[1]{\oldparacol{#1}%
\everypar{\abortparagraph}%
\setlength{\columnheight}{0pt}%
\setlength{\columnroom}{\@colroom}%
\global\edef\leftcolumnpage{\arabic{page}}%
\global\edef\rightcolumnpage{\arabic{page}}%
}

% write notes in right column

\newcommand{\columnnote}[1]% #1 = text for second column
{\refstepcounter{columnnote}%
\darkmark{\thecolumnnote}%
\@ifundefined{columnnotepage\thechapter.\thecolumnnote}{}%
{\def\leftcolumnpage{\csname columnnotepage\thechapter.\thecolumnnote\endcsname}}%
\ifnum\rightcolumnpage<\leftcolumnpage\relax% synchronize pages
\global\columnroom=\textheight
\global\columnheight=0pt
\switchcolumn[1]%
\loop\ifnum\c@page<\leftcolumnpage \strut\newpage\repeat
\global\edef\rightcolumnpage{\arabic{page}}%
\switchcolumn[0]%
\fi
\bgroup% compute size of note
\setbox0=\hbox{\begin{minipage}{\dimexpr \columnwidth-\bibindent}#1\end{minipage}}%
\global\advance\columnheight by \dimexpr \baselineskip + \ht0 + \dp0\relax
\egroup
\ifdim\columnheight>\columnroom\relax% time to break page
\immediate\write\@auxout{\string\newabortparagraph {\theparagraph}}%
\switchcolumn[1]%
\strut\newpage%
\global\edef\rightcolumnpage{\arabic{page}}
\switchcolumn[0]%
\global\columnroom=\textheight
\bgroup% re-compute size of note
\setbox0=\hbox{\begin{minipage}{\dimexpr \columnwidth-\bibindent}#1\end{minipage}}%
\global\columnheight=\dimexpr \baselineskip + \ht0 + \dp0\relax
\egroup
\else
\immediate\write\@auxout{\string\columnnotepage {\thechapter.\thecolumnnote}{\thepage}}%
\fi
\switchcolumn[1]%
\noindent\hspace{\bibindent}%
\begin{minipage}{\dimexpr \columnwidth-\bibindent}%
\mbox{\llap{\darkmark{\thecolumnnote}}%
\color{lightgray}\rule[-0.2\baselineskip]{\textwidth}{\baselineskip}}%
\linebreak#1\end{minipage}%
\linebreak\vspace{\marginparpush}%
\switchcolumn[0]%
}
\makeatother

\begin{document}
\setcounter{abortparagraph}{1}% reuse counter after aux file read
\chapter{One}
\begin{paracol}{2}
Blind text.

Lorem ipsum dolor sit amet. \columnnote{This is the first footnote.''}

The quick brown fox jumped over the lazy dog. \columnnote{This is the second footnote.''}

Too big for the page.  \columnnote{\rule{1pt}{.9\textheight}}

Next paragraph.
\end{paracol}
\end{document}


It should be noted that \switchcolumn doesn't synchronize the pages either. That had to be done separately. Note that \thepage is not reliable when paragraphs are split over two pages, so are saved to the aux file instead. Also, one must be careful to NOT synchronize the aborted paragraphs as they NEED to fail the test every time.

• I already have the number layout done with TikZ. The real hard part is still the vertical alignment, since marginpar is a long way off from the intended alignment. MWE coming. – Simon Kuang Aug 5 '15 at 15:52
• Have you looked at the sidenote package, together with marginfix ? Appart from the shape of numbers (which you can probably redefine), I think it looks like what you are searching for. – mvienney Aug 5 '15 at 16:45
• @mvienney memoir's sidebar looks hopeful. – Simon Kuang Aug 5 '15 at 18:24
• By the way, OP stands for Original Post, I think. – Simon Kuang Aug 5 '15 at 20:39
• I just replaced the entire answer, so old comments are now out of context. – John Kormylo Aug 5 '15 at 22:31