# Position margin notes relative to left margin in plain TeX

I want to add margin notes in the Tufte style to my Plain TeX document. (I'm using eplain, if that matters.) I know that if I were using LaTeX I could just use tufte-latex, but as a thorough contrarian I enjoy coding these things myself.

I'm almost there but my current macro will place text relative to the current location when I invoke it, instead of the margin. In my MWE, the note is placed smack dab in the middle of things. But if you move the invocation of \sidenote around, the side note may appear closer to the left margin. How can I reposition my sidenote text relative to the left (or right) margin, instead of the current location? (I used the left margin in my MWE.)

The thing I really do like about my macro is that the baselines of the first line of the side note and the main body text to which it refers align. I want to keep that. And any other suggestions about my macro are welcome.

MWE:

\input eplain
\leftmargin=2in

\font\sidenotefont=      pxi at8.5pt

\long\def\sidenote#1{\llap{\smash{\vtop{%
\parindent=0pt\hsize=1.5in\rightskip=.87in\parfillskip=0pt\leftskip=-1in plus1fil%
\baselineskip=10pt\sidenotefont #1}}}}

When we are working at a difficult task and strive after a good thing, we are
fighting a righteous battle, the direct reward of which is that we are kept from
\sidenote{This note has been brought to you by the letter pi and
the number e. Please make a note of it. The reason for its existence is the
great lengths I went to do things.}much evil. As we advance in life it becomes more and more difficult, but in
fighting the difficulties the inmost strength of the heart is developed. Indeed
life is a have to defend and protect ourselves, and with a cheerful and brace
spirit we must battle; we plan and calculate in order to make progress.

\bye

-
Would an \insert-based solution work for you? i.e., output routine. – morbusg Dec 8 '12 at 10:04
@morbusg, I was looking at \insert yesterday. I was concerned that I wouldn't be able to easily get the alignment right; sidenotes must be beside the text the're commenting on. Do you know if this can be done? – EfForEffort Dec 8 '12 at 12:58
Ah, yes, it gets very difficult then; I know because I have tried (and failed). I think \pagetotal could somehow be used for those calculations, but the problems (again: at least for me) arise when there are more than one sidenote on a page. – morbusg Dec 8 '12 at 20:36

If lines don't have unusual depth, this could be a starting point:

\input eplain
\leftmargin=2in

\font\mainfont=pxr at 10pt
\font\sidenotefont=pxi at 8.5pt

\long\def\sidenote#1{%
\parindent=0pt
\hsize=1.7in
\parfillskip=0pt
\leftskip=0pt plus1fil
\baselineskip=10pt\sidenotefont\vglue-\ht\strutbox #1}}\kern1em}}}

\mainfont

When we are working at a difficult task and strive after a good thing, we
are fighting a righteous battle, the direct reward of which is that we are
kept from \sidenote{This note has been brought to you by the letter pi and
the number e. Please make a note of it. The reason for its existence is the
great lengths I went to do things.}much evil. As we advance in life it becomes
more and more difficult, but in fighting the difficulties the inmost strength
of the heart is developed. Indeed life is a have to defend and protect ourselves,
and with a cheerful and brace spirit we must battle; we plan and calculate in
order to make progress.

\bye


The key is \vadjust that adds the material to the enclosing vertical list.

-
This is great, thanks! Now to learn what strutbox is and how I can adjust it for different font sizes.... – EfForEffort Dec 8 '12 at 14:37
@D.Bueno: You might want to look at exercise 14.28 of the TeXbook (and it's answer in the Appendix A). The solution is very similar to egreg's proposal and Knuth's explanations are always nice, so it's a good read. – Mafra Dec 8 '12 at 23:08
@D.Bueno: For that, you could use LaTeX's definition of the strutbox; it uses .7\baselineskip for height, and .3\baselineskip for depth, instead of “hard-coded” values as in plain. Also you might want to set \parskip=0pt to avoid possible “drifting” of baselines between the main column content and the sidenote column (plain's default is 0pt plus 1pt). – morbusg Dec 11 '12 at 6:26
@morbusg: Thanks! These are good suggestions. – EfForEffort Dec 11 '12 at 19:59

After reading the appropriate exercise in the TeXBook (14.28), here is my \strut-based solution. Thanks to @Mafra for suggesting the exercise.

\def\strutdepth{\dp\strutbox}
\def\simplesidenote#1{%
\def\lsidenote#1{\vtop to \strutdepth{%
\baselineskip\strutdepth%
\vss\llap{\vtop to 0pt{%
\leftskip=0pt plus1fill \rightskip=8pt%
\parfillskip=0pt \parindent=0pt%
\hsize=1.7in%
\eightpoint\it #1}}\null}}


Note that \eightpoint is just a macro to adjust the font size.

-
Heh, I think I suggested exercise 14.28 :-) – Mafra Dec 12 '12 at 23:22
lol. Indeed, you did. Sorry about that! I've corrected it in the answer. – EfForEffort Dec 12 '12 at 23:30

There is a great macro written by Petr Olsak from the Czech Republic, which perhaps beats even eplain. Olsak is notorious for prefering plainTeX over LaTeX, and he wrote this macro in order to offer the power of LaTeX to plainTeX users. The name of the file (opmac.tex) actually stand for Olsak's Plaintex MACros.

http://petr.olsak.net/opmac-e.html

Documentation is available in English, too. After installing and \input opmac you can just type \mnote{your text in margin} and it will place it accordingly, in the left margin on odd pages, in the right margins on even ones, unless you have reason to have them on the same side of all pages. Everything can be setup, as you'll learn in the documentation.

-
Hello, this does not directly answer the question of positioning the margin notes w.r.t. the page boundary. "Read the documentation", as you suggest, certainly does not stand as an answer to the TeX.SX standards. – yo' Jan 7 '15 at 10:17
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – mafp Jan 7 '15 at 10:40
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post. – Masroor Jan 7 '15 at 10:43

I want point out that there are problems in the previous answers and give more simple solution.

The egerg's answer includes the ad-hoc correction \vglue-\ht\strutbox. The vertical positioning of the margin note text depends on the depth of the line in the paragraph and on the height of the first line in the note text in his solution. You can try to remove all letters and characters with non-zero descenders from the second line of the paragraph in the example (i.e. g, p, comma, etc.) and you can see that the marginal note position will be bad. This bug is malicious because the code \vglue-\ht\strutbox seems that there is some reason for this. But it is not true. The \vskip-8.5pt does the same work and don't remove the accidental position of the marginal note.

The EfForEffort's answer is bad, because the \baselineskip is set to small value in the \vtop resulting the lines without equidistant baseline: the lines are leaning each against other with small vertical space 1pt which is default from the \lineskip register.

The Knuth's answer to exercise 14.28 from TeXbook (print star to the left margin using \marginstar macro):

\def\strutdepth{\dp\strutbox}
\def\specialstar{\vtop to \strutdepth{
\baselineskip\strutdepth
\vss\llap{* }\null}}


is overcomplicated because there is \vtop to\strutdepth followed by setting \baselineskip=\strutdepth followed by \null terminator in the \vtop. Much more simple is this solution of the 14.28 excercise:

\def\marginalstar{\strut\vadjust{\kern-\dp\strutbox\smash{\llap{* }}\kern\dp\strutbox}}


If you need more lines in the margin note:

\let\mnotefont=\tenit
\def\mnoteA#1{\smash{\llap{\hbox{\vtop{\mnoteB#1}\kern1em}}}}
\def\mnoteB{\hsize=1.7in \parindent=0pt \leftskip=0pt plus1fill \mnotefont}

When we are working at a difficult task and strive after a good thing, we
are fighting a righteous battle, the direct reward of which is that we are
kept from%
\mnote{This note has been brought to you by the letter pi and the number e.
Please make a note of it. The reason for its existence is the great
lengths I went to do things.}
much evil. As we advance in life it becomes more and
more difficult, but in fighting the difficulties the inmost strength of the
heart is developed. Indeed life is a have to defend and protect ourselves,
and with a cheerful and brace spirit we must battle; we plan and calculate
in order to make progress.

\bye


If you are using OPmac:

\input opmac
\fixmnotes\left \mnotesize=1.7in \def\mnotehook{\typosize[8/10]\it}
\margins/1 letter (2.5,1,1,1)in

When we are working at a difficult task and strive after a good thing, we
are fighting a righteous battle, the direct reward of which is that we are
kept from%
\mnote{This note has been brought to you by the letter pi and the number e.
Please make a note of it. The reason for its existence is the great
lengths I went to do things.}
much evil. As we advance in life it becomes more and
more difficult, but in fighting the difficulties the inmost strength of the
heart is developed. Indeed life is a have to defend and protect ourselves,
and with a cheerful and brace spirit we must battle; we plan and calculate
in order to make progress.

\bye

-
Maybe with his macro Knuth wanted to preserve \prevdepth? Does your macro do this? – Igor Liferenko Sep 2 '15 at 6:38
Also, I see a problem with using \strut here: if a letter in the next line after margin star is higher than 8.5pt, \lineskip will be used, so the paragraph will be "opened up". Your solution also uses \strut. Is there a solution which does not use \strut at all? – Igor Liferenko Sep 2 '15 at 7:12
Is a solution, which is based on \prevdepth, possible? – Igor Liferenko Sep 2 '15 at 8:43
@IgorLiferenko IMHO, the solution based on \prevdepth is impossible. Reason: \vadjust{...} processes its parameter immediately in order to produce the vertical list. All main processor calculation (if exist) is done at this time. The \prevdepth of the previous line is unknown now, because the such line is unknown. In the second step, when the generated vertical list is distributed after the line of the processed paragraph, no macro expansion, no main processor calculation is performed. The vertical list form \vadjust is only added after the line without \prevdepth re-calculation. – wipet Sep 2 '15 at 10:10
The answer to exercise 14.28 says: "because the depth of the line depends on details of line breaking that aren’t known until afterwards". To me, it looks like a shortcoming: why Knuth just could not postpone the calculation of \vadjust until the actual event of adding it to vertical list? Is there some reason for this which I ignore? Are there any other TeX engines (especially e-TeX) which allow this to be done? – Igor Liferenko Sep 2 '15 at 12:02