How to merge marginpars to avoid overflows?

I am using margins to print keywords but sometimes the number of keywords in a paragraph become too many and they appear beside the next paragraphs. To avoid this issue, I thought maybe they could be done in a way that the texts in the margin are separated by commas instead of new lines if their corresponding \marginpars are on the same line of text.

For example, assume I write:

Some text A\marginpar{X} and B\marginpar{Y}


In the output, A and B are printed on the same line. Then I want to have "X,Y" in the margin area instead of "X" on one line and "Y" on its next line.

Is there a way to modify \marginpar or define a new command for this purpose?

• By default, \marginpar is a (margin) float and is not printed on top of one another. What \documentclass are you using? – Werner Jun 17 '13 at 1:51
• Sorry, if I did not write clearly. I meant they will be stacked (not printed on top of one another) and exceed paragraph heights if there are many of them in a paragraph. I want to merge them to avoid going to next paragraphs in those cases. – Reza Jun 17 '13 at 2:06
• Cute as it may seem to you, I wouldn't want to have marginal paragraphs full with keywords. Have you thought of creating an index? If that isn't a solution, perhaps there are other solutions. Maybe "sticky notes" could help. Can you write a bit more about the context of the document you're writing? – user10274 Jun 17 '13 at 3:45
• I saw the idea of putting terms in margins in "Graph Theory" book by Diestel and find it very helpful specially for print versions which cannot be searched. The document that I am writing is my thesis (subjects: math, graph theory, algorithm). I do have an index, but I want to have them on the sides too be found easier. It is not that I have margins full of terms all the time, but in very few paragraphs overflow happens and I wanted to have a polished solution for it. – Reza Jun 17 '13 at 4:01
• you might want the 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.” – cgnieder Jun 17 '13 at 17:54

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}


• Thanks Niel, this solution is indeed very helpful for manual workaround. If I could not manage to find a automatic solution, I probably will use your idea. – Reza Jun 19 '13 at 1:00
• @Reza: Thanks. I've also just made a minor revision to the code to improve its performance in some small ways. – Niel de Beaudrap Jun 19 '13 at 13:02

I think you can just use one \marginpar, instead of many to solve this problem. Just separate each keywords by comma.

• This could help but I do not want to merge all of them. I want to merge two of them only if they are printed in the same line and I will not know this before compiling. – Reza Jun 17 '13 at 2:04