I don't know if there is a way to do this automatically: I think that the way that TeX formats whole paragraphs, deciding line breaks only when the paragraph is complete, prevents any simple local knowledge of whether two words (or macros inserted between words) will end up on the same line of text.
However, I can provide a solution for the next best thing: a macro which will allow you to manually — but as easily as possible — determine which margin notes go inside the same \marginpar
.
Macros for margin notes with continuations
The following are two macros which differ only by a star. While it is less than ideal to have to go through your document adding stars to commands, hopefully it will be easy to find (or guess) a handful of places where you should add a star, and modify your source code appropriately.
Syntax: \marnote{ ... }
or \marnote*{ ... }
The unstarred macro creates a new margin note. The starred version adds material to be included into the previously defined margin note. Both commands take their argument, and write a command to be read from the auxiliary file which builds the content of a given margin note.
The starred version writes a comment in the auxiliary file which appends to the end of a token list which already contains some material. Both versions take the contents of the token list as it is being built, and define a named macro representing the contents of the desired margin note. At compilation time, whatever the contents of that macro are defined to be by the auxiliary file, goes into the margin note. Because the contents of the auxiliary file can lag behind the document itself, a couple of compilations (which may or may not be performed automatically by your editor) will be necessary after each changes to the margin notes.
Code:
\makeatletter
\newcounter{marnote}
\setcounter{marnote}{0}
\newtoks\marnote@toks
\def\marnote{\@ifstar{\marnote@continue}{\marnote@new}}
\def\marnote@new#1{%
\@bsphack
\fix@marnote
\stepcounter{marnote}%
\expandafter\put@marnote\expandafter{marnote@\the\c@marnote}%
\protected@write\@auxout{}{\string\newmarnote{#1}}%
\@esphack}
\def\marnote@continue#1{%
\@bsphack\protected@write\@auxout{}{\string\continuemarnote{#1}}\@esphack}
\def\put@marnote#1{%
\marginpar{%
\@ifundefined{#1}%
{\nfss@text{\reset@font\marnotestyle\bfseries ??}}%
{\csname #1\endcsname}%
}}
\def\fix@marnote{%
\ifnum\c@marnote>0\protected@write\@auxout{}{\string\savemarnote\the\c@marnote}\fi}
\def\newmarnote#1{%
\marnote@toks={\marnotestyle {#1}}}%
\def\continuemarnote#1{%
\marnote@toks=\expandafter{\the\marnote@toks\marnotedelim#1}}%
\def\savemarnote#1{%
\def\@tempa{\expandafter\gdef\csname marnote@#1\endcsname}%
\expandafter\@tempa\expandafter{\the\marnote@toks}}%
\AtEndDocument{\@bsphack\fix@marnote\@esphack}
\makeatother
\newcommand\marnotestyle{\footnotesize}
\newcommand\marnotedelim{, }
Note the two macros defined at the end, which will allow you to modify how the margin notes are typeset.
Sample document
Include the code above in the preamble of the following document — or copy the following into a new document, after the margin note macros above.
\documentclass{article}
% For some "dummy" text at the end of the document
\usepackage[english]{babel}
\usepackage{blindtext}
% Some geometric parameters to better show off the margin notes
\usepackage[right=8cm,textwidth=7cm,marginparwidth=6cm, marginparsep=5mm]{geometry}
% This allows the margin notes to align as well as possible with the lines of text
\setlength\marginparpush{0pt}
\begin{document}
Testing testing one\marnote{one (1)} two three four five six seven
eight\marnote{eight (8)} nine\marnote*{nine (9)} ten eleven twelve
thirteen\marnote*{thirteen (13)} fourteen fifteen sixteen seventeen
eighteen\marnote{eighteen (18)} nineteen twenty. \blindtext[1]
\end{document}
\marginpar
is a (margin) float and is not printed on top of one another. What\documentclass
are you using?marginfix
package. From its documentation: “Authors using LaTaX to typeset books with significant margin material often run into the problem of long notes running off the bottom of the page. [...] This package implements a solution to make marginpars “just work” by keeping a list of floating inserts and arranging them intelligently in the output routine.”