3

I'd like to wrap certain chunks of text in my Plain TeX document so that, to the right of each line in the chunk, a specific character is printed in the right margin.

All of these characters should be at the same horizontal position in the margin, say 3ex to the right of the text chunk's right margin.

Using a vertical bar | as the character will let me show which chunks of text in the document have been modified versus the previous draft of the document.

LaTeX has a package to mark changes with marginal bars, but none seems available in TeX. The method I'm proposing here is not esthetically beautiful, but will get the job done and seems likely to be simple to implement. If, however, it is not possible to wrap arbitrary chunks of text in this way, then I could live with wrapping whole paragraphs.

I could imagine a macro like \markchunk{Four score and eight years ago} or a pair of macros like:

\markstart
Four score and eight years ago
\markend

Thank you!

  • Did you look at the code of the LaTeX package (which one is it?) to see if you can adapt it to Plain? Can you show us what code you've tried? – musarithmia Feb 7 '15 at 2:10
  • I did look at the LaTeX changebar package, but the code was immense and, to my poor eyes, inscrutable. The TeXBook, on pages 105 and 316, presents the \marginalstar macro to put a character in the right margin. This doesn't work for me because, if I had a big chunk that covered 20 lines on the typset page, I would have to make 20 calls to marginalstar, plus I would not know where the line breaks are. – Iron Pillow Feb 7 '15 at 2:14
  • Oh, I also looked at EDMAC, but am so dim that I could not even locate the file that had the EDMAC code in it. I'm thinking that there is some end-of-line macro or parameter that can be altered to do this. – Iron Pillow Feb 7 '15 at 2:19
  • If the code is immense it's probably because this is hard to implement. If using LaTeX and changebar isn't an option, perhaps you could make your \markstart and \markend macros be calls to \marginalstar with different characters just to indicate the beginning and end of the passage. – musarithmia Feb 7 '15 at 4:39
  • 1
    Marking single lines is pretty easy - you can use \vadjust to put a rule in the margin - but general multiline revision bars is a much more complex problem; you need to add markers and write an output routine to find them and add bars to the output pages at the right points. David Salomon's Advanced Texbook has an extended example showing one possible approach. – Thruston Feb 7 '15 at 11:43
4

My solution is based on the \pdfsavepos primitive form pdfTeX. The positions of \markstart and \markstop are saved to \jobname.pos file and the data from this file are reused in the next TeX run. The data are re-calculated from positions of start and stop marks to the position of start mark plus distance from start to stop mark. This calculation is done in \posX macro and it is slightly complicated because we need to calculate the page breaks between start and stop marks. The result of the calculation is the set of macros \pos:pagenumber in the form \posA{position}{distance}\posA{position}{distance} etc. These macros are finally used in the \output routine to draw the bars from position+10pt with the lenght distance+12pt. This is the reason why the \pagebody from plain TeX output routine is redefined.

\def\markchunk#1{\markstart #1\markstop}
\def\markstart{\leavevmode\writepos B}
\def\markstop{\writepos E}

\newdimen\botmargin
\ifdim\pdfpageheight=0pt \pdfpageheight=297mm \fi                           
\botmargin=\pdfpageheight \advance\botmargin by-\vsize
\advance\botmargin by-1in \advance\botmargin by-\voffset

\newcount\tmpnum
\def\posX#1#2#3#4{%
   \expandafter\ifx\csname pos:#2\endcsname\relax
      \expandafter\def\csname pos:#2\endcsname{}%
      \tmpnum=\botmargin \advance\tmpnum by\vsize \advance\tmpnum by-\topskip
   \fi
   \ifx#1B%
      \expandafter\edef\csname pos:#2\endcsname{\csname pos:#2\endcsname \posA{#4}}%
      \tmpnum=#4
   \else \expandafter\ifx\csname pos:#2\endcsname\empty
            \expandafter\edef\csname pos:#2\endcsname{\posA{\the\tmpnum}}%
         \fi
      \advance\tmpnum by-#4
      \expandafter\edef\csname pos:#2\endcsname{\csname pos:#2\endcsname{\the\tmpnum}}%     
      \tmpnum=-1
   \fi
}
\def\posY#1{%
   \expandafter\ifx\csname pos:#1\endcsname\relax \else
      \ifnum\tmpnum<0 \else
         \advance\tmpnum by-\botmargin
         \expandafter\edef\csname pos:#1\endcsname{\csname pos:#1\endcsname{\the\tmpnum}}%
   \fi\fi
}
\newread\testin
\def\softinput #1 {\let\next=\relax \openin\testin=#1
  \ifeof\testin \message{Warning: the file #1 does not exist}%
  \else \closein\testin \def\next{\input #1 }\fi
  \next
}
\let\posA=\relax \softinput\jobname.pos

\newwrite\posfile
\immediate\openout\posfile=\jobname.pos
\def\writepos#1{\pdfsavepos
   \write\posfile{\string\posX\space#1{\the\pageno}{\the\pdflastxpos}{\the\pdflastypos}}}

\def\posA#1#2{\vbox to0pt{\kern\botmargin\kern-#1sp\kern-10pt
   \rlap{\vrule height 12pt depth#2sp}\vss}}

\def\pagebody{\hbox{\vbox to\vsize{\boxmaxdepth\maxdepth \pagecontents}%
   \write\posfile{\string\posY{\the\pageno}}%
   \rlap{\kern10pt \csname pos:\the\pageno\endcsname}}}

I'd like to wrap certain chunks of text in my Plain TeX document so that, to
the right of each line in the chunk, a specific character is printed in the 
right margin. \markchunk{Four score and eight years ago.}
All of these characters should be at the same horizontal position in the
margin, say 3ex to the right of the text chunk's right margin.

I'd like to wrap certain chunks of text in my Plain TeX document so that, to
the right of each line in the chunk, a specific character is printed in the 
right margin. And the test. \markchunk{Four score and eight years ago.}
All of these characters should be at the same horizontal position in the
margin, say 3ex to the right of the text chunk's right margin.

\markstart
LaTeX has a package to mark changes with marginal bars, but none seems
available in TeX. The method I'm proposing here is not esthetically   
beautiful, but will get the job done and seems likely to be simple to 
implement. If, however, it is not possible to wrap arbitrary chunks of text
in this way, then I could live with wrapping whole paragraphs.
\markstop

\bye
  • You are my hero. Works exactly as advertised on my big hairy document. This is rather a more complicated solution than I'd envisioned (redefining the TeX \pagebody routine is a bit fragile), but it produces a far nicer output than the grubby hack that my question asked for. With a little care, I think this could be used as a Plain TeX substitute for the core feature of LaTeX's changebar package. Thank you. – Iron Pillow Feb 24 '15 at 0:57
  • @IronPillow Fine. Maybe it would be more exact to change the title of this thread. Something like: putting a bar alongside the text in plain TeX. – wipet Feb 24 '15 at 5:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.