3

I am writing scripts to produce synchronized texts as an aid to language study. I would like multiple streams of text to flow together in paragraphs, synchronizing where I indicate and otherwise flowing independently.

enter image description here This second example is not an example of linguistic "gloss", and cannot be produced using the linguistics packages that have been suggested so far. Note how the two parallel streams of text have independent line breaks:

enter image description here I know enough TeX and LaTeX to believe that this would be very difficult to do in one pass, entirely in TeX. Were I to code this now, I'd measure every word in a first LaTeX pass, then use an external programming language to plan the paragraphs for a second LaTeX pass. The idea of expressing the necessary logic in TeX sounds excruciating to me.

It would not surprise me, however, if someone knows or can imagine how to do this entirely in TeX or LaTex. Is this possible?

This may be a "hardware store" puzzle: The part I want is labeled for a different purpose, and I won't know what to ask for until I can guess that purpose. What's another problem like this one, that has already been solved? In-place footnotes?

I am aware of parallel text, side by side. That is what I do now. It is too much eye travel and alignment stress. If QWERTY were that much finger travel, everyone would have switched to DVORAK by now.

I am aware of stacking boxes, to flow as indivisible entities in a paragraph. That may be what I do as a first draft, but it wastes space. Interleaved text that flows can borrow space from each other, and can break where needed.

In some applications, the interleaved texts might be several languages, synchronized as closely as the translations allow. There are off-the-shelf tools such as "hunalign" for synchronizing texts, as this is a standard step in AI language learning. For that application, I would surely end up with some blocks that don't fit on a line. I need the streams to independently flow.

  • 1
    You could do it using expex and LuaTeX if you want something more automated. It depends on your opinion about Lua embedded in LuaTeX being "pure (La)TeX" or not. –  Jul 06 '20 at 20:34
  • Thanks. I didn't know about linguist's "interlinear gloss". Alas, the Leipzig Glossing Rules get in my way: I want unannotated primary text to be able to kern right into free space above the next annotation. I'm starting to see how I could build up such boxes line by line. That's not the same as several interleaved lines of flowing text, with automatic line breaking, synchronizing at specificed locations. Unlike every Lisp book ever written, there's no dumbed down "TeX in Tex" code sample I can start from, to rewrite TeX's paragraph engine. I'll settle for flush left and no flexible glue. – Syzygies Jul 06 '20 at 23:09
  • @AlanMunn Other than using the word "linguistics", I'm not seeing how that's related. Am I missing something? – Teepeemm Jul 07 '20 at 01:35
  • @Teepeemm take a look at the ExPex package. What you are describing is how linguistics examples are formatted. Not the numbering part but the glossing part. See also e.g. https://tex.stackexchange.com/q/45520/2693 – Alan Munn Jul 07 '20 at 01:42
  • @AlanMunn Ah. I was looking at the question and the first halves of each of your examples. The second halves do indeed seem to fit the bill. – Teepeemm Jul 07 '20 at 01:51
  • I added a second illustration, showing parallel phrases flowing independently in a paragraph. They are synchronized between phrases, but words break independently between lines. The linguistics packages do not do this. What the linguistics packages do can be accomplished by a basic use of boxes. Is there a package that can interleave several streams of text, with independent line breaks? – Syzygies Jul 07 '20 at 09:41
  • I've read what I can about the TeX line-breaking engine, and my impression is that its design is not sufficiently general to support multiple indendpent streams. A single stream is hard-wired into the code. If so, one will find thousands of packages that work within this limitation, and none whatsoever that fix this limitation. I could be wrong, but this is a tecnical question for those who understand that engine. – Syzygies Jul 07 '20 at 09:43
  • It's almost as if, with double-spacing, TextA is to go on one row, and TextB on the other (with some saveboxes, and everything done before AtShipout; or a double-print overlay onto the same page). Or even lines and odd lines. The glossing uses tabular to line things up, so works vertically. We need a horizontal equivalent. – Cicada Jul 07 '20 at 12:02
  • @Cicada Neither of the glossing packages use tabular for formatting. It's all done with boxes. But the second example makes things clearer, and this is no longer a duplicate. – Alan Munn Jul 07 '20 at 12:34
  • @AlanMunn Thanks! I was visualising columns, and slipped into table-like concepts. I'm going to try double-spacing, a savebox (with extra line at the top), and printing the savebox as overlay at page shipout. Will have to learn a few things as a first step, though. – Cicada Jul 08 '20 at 13:34
  • @JairoADelRio I read through The TeX FAQ trying to fill holes in my TeX programming chops, wondering if I need to contribute TeX to rosettacode.org. I didn't even see a clean way to iterate through the next word in one of two lists, necessary for building pairs of lines manually in vertical mode. So this time I focused on LuaTeX in your comment, even though expex doesn't require it. Clearly, two TeX passes and an external program would be the easiest way to implement what I want now, but switching to LuaTeX would be well worth the investment. – Syzygies Jul 08 '20 at 14:21

1 Answers1

2

Yes, coding seems the pragmatic way. Coordinates on the page have to be transferred between two iterators.

TikZ allows a proof of concept of free-stream text interleaving at paragraph-level, with the overlay option (one picture on top of the other):

Raw interleaving:

raw interleaving

With (manual) spacing added:

spaced interleaving

Coding, with Lua (or expl3?), will probably be the easiest method to synchronise sentence starts.

MWE

\documentclass{article}
\usepackage{xcolor}
\usepackage{fontspec}
\setmainfont{Noto Serif}
\setsansfont{Noto Sans}
\usepackage{tikz}
\usepackage{setspace}

\begin{document} \doublespacing \fbox{% \begin{tikzpicture}[remember picture] \node (a) [text width=0.98\textwidth, minimum width=0.98\textwidth] {the objects in space and time are what first give rise to human reason. Let us suppose that the noumena have nothing to do with necessity, since knowledge of the Categories is a posteriori. Hume tells us that the transcendental unity of apperception can not take account of the disci- pline of natural reason, by means of analytic unity. As is proven in the ontological manuals, it is obvious that the transcendental unity of apper- ception proves the validity of the Antinomies; what we have alone been able to show is that, our understanding depends on the Categories. It remains a mystery why the Ideal stands in need of reason. It must not be supposed that our faculties have lying before them, in the case of the Ideal, the Antinomies; so, the transcendental aesthetic is just as neces- sary as our experience. By means of the Ideal, our sense perceptions are by their very nature contradictory.\ \ \ \ \ \ }; \end{tikzpicture}\ }%fbox

\color{red}\sffamily

\begin{tikzpicture}[remember picture,overlay] \node (b) at (a) [yshift=1.6ex,text width=0.98\textwidth, minimum width=0.98\textwidth] {Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus lit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum ravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulpu ate a, magna. Donec vehicula augue eu neque. Pellentesque habitan morbi tristique senectus et netus et malesuada fames ac turpis egestas Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et lectus vestibulum rna fringilla ultrices. Phasellus eu tellus sit amet tortor gravida placerat nteger sapien est, iaculis in, pretium quis, viverra ac, nunc. Praesent ege em vel leo ultrices bibendum. Aenean faucibus. Morbi dolor nulla, male uada eu, pulvinar at, mollis ac, nulla. Curabitur auctor semper nulla onec varius orci eget risus. Duis nibh mi, congue eu, accumsan eleifend agittis quis, diam. Duis eget orci sit amet orci dignissim rutrum. Nam du gula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor orem non justo. Nam lacus libero, pretium at, lobortis vitae, ultricies et %ellus. Donec aliquet, tortor sed accumsan bibendum, erat ligula alique %magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mol %s. Suspendisse ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis %atoque penatibus et magnis dis parturient montes, nascetur ridiculus %mus. Aliquam tincidunt urna. Nulla ullamcorper vestibulum turpis. Pel %entesque cursus luctus mauris. Nulla malesuada porttitor diam. Donec %elis erat, congue non, volutpat at, tincidunt tristique, libero. Vivamus %iverra fermentum felis. Donec nonummy pellentesque ante. Phasel %us adipiscing semper elit. Proin fermentum massa ac quam. Sed diam }; \end{tikzpicture}

\color{black}\rmfamily \newpage

\hfill Project Gutenberg: Jules Verne

\fbox{% \begin{tikzpicture}[remember picture] \node (c) [text width=0.98\textwidth, minimum width=0.98\textwidth] {«Remontons-nous? -- Non! Au contraire! Nous descendons! -- Pis que cela, monsieur Cyrus! Nous tombons! -- Pour Dieu! Jetez du lest! -- Voilà le dernier sac vidé! -- Le ballon se relève-t-il? -- Non! -- J'entends comme un clapotement de vagues! -- La mer est sous la nacelle! -- Elle ne doit pas être à cinq cents pieds de nous!» Alors une voix puissante déchira l'air, et ces mots retentirent: «Dehors tout ce qui pèse!... tout! et à la grâce de Dieu!» \ \ }; \end{tikzpicture} }%fbox

\color{red}\sffamily \begin{tikzpicture}[remember picture,overlay] \node (d) at (c) [yshift=1.5ex,text width=0.98\textwidth, minimum width=0.98\textwidth] {“Are we rising again?” “No. On the contrary.” “Are we descending?” “Worse than that, captain! we are falling!” “For Heaven’s sake heave out the ballast!” “There! the last sack is empty!” “Does the balloon rise?” “No!” “I hear a noise like the dashing of waves. The sea is below the car! It cannot be more than 500 feet from us!” “Overboard with every weight! ... everything!”}; \end{tikzpicture}

\color{black}\rmfamily \newpage

\hfill Project Gutenberg: Jules Verne

\fbox{% \begin{tikzpicture}[remember picture] \node (e) [text width=0.98\textwidth, minimum width=0.98\textwidth] {«Remontons-nous? -- Non! Au contraire! Nous descendons! -- Pis que cela, monsieur Cyrus! Nous tombons! -- Pour Dieu! Jetez du lest! \hspace{7em}-- Voilà le dernier sac vidé! -- Le ballon se relève-t-il? -- Non! -- J'entends comme un clapotement de vagues! -- La mer est sous la nacelle! -- Elle ne doit pas être à cinq cents pieds de nous!» Alors une voix puissante déchira l'air, et ces mots retentirent: «Dehors tout ce qui pèse!... tout! et à la grâce de Dieu!» \ \ }; \end{tikzpicture} }%fbox

\color{red}\sffamily \begin{tikzpicture}[remember picture,overlay] \node (f) at (e) [yshift=-0.2ex,text width=0.98\textwidth, minimum width=0.98\textwidth] {“Are we rising again?” “No. On the contrary.” “Are we descending?” “Worse than that, captain! we are falling!” “For Heaven’s sake heave out the ballast!” “There! the last sack is empty!” “Does the balloon rise?” “No!” “I hear a noise like the dashing of waves. \hspace{4em}The sea is below the car! \hspace{4.5em}It cannot be more than 500 feet from us!” \hspace{5em}\ \ \ \ “Overboard with every weight! ... everything!”}; \end{tikzpicture}

\end{document}


Addendum

Experimenting a bit in TikZ, starting sentences flush left for a paragraph seems more readable, and also automatically synchronizes them x-wise (obviously). Perhaps an array/matrix/grid structure could be used for the start position of run-in sentences.

parcourait

MWE for the above, partially macro-ised:

\documentclass{article}
\usepackage{xcolor}
\usepackage{fontspec}
\setmainfont{Noto Serif}
\setsansfont{Noto Sans}
\usepackage{tikz}
\usepackage{setspace}
\usepackage{pgffor}

%============================================ \newcommand\doubleb[3]{% \color{black}\rmfamily \newpage \fbox{% \begin{tikzpicture}[remember picture] \node (i) [text width=0.98\textwidth, minimum width=0.98\textwidth] {#1\foreach \x in {1,...,#3}{\ \ }}; \end{tikzpicture} }%fbox \color{red}\sffamily \begin{tikzpicture}[remember picture,overlay] \node (j) at (i) [,text width=0.98\textwidth, minimum width=0.98\textwidth] {#2}; \end{tikzpicture} } %============================================ \begin{document} \doublespacing

\doubleb{Or, au moment même où tant de catastrophes s'accomplissaient sur terre et sur mer, un drame, non moins saisissant, se jouait dans les airs bouleversés. \ En effet, un ballon, porté comme une boule au sommet d'une trombe, et pris dans le mouvement giratoire de la colonne d'air, parcourait l'espace avec une vitesse de quatre-vingt-dix milles à l'heure, en tournant sur lui-même, comme s'il eût été saisi par quelque maelström aérien. \ Au-dessous de l'appendice inférieur de ce ballon oscillait une nacelle, qui contenait cinq passagers, à peine visibles au milieu de ces épaisses vapeurs, mêlées d'eau pulvérisée, qui traînaient jusqu'à la surface de l'Océan.}{But while so many catastrophes were taking place on land and at sea, a drama not less exciting was being enacted in the agitated air.\ \ \ In fact, a balloon, as a ball might be carried on the summit of a waterspout, had been taken into the circling movement of a column of air and had traversed space at the rate of ninety miles an hour, turning round and round as if seized by some aerial maelstrom.\ \ \ Beneath the lower point of the balloon swung a car, containing five passengers, scarcely visible in the midst of the thick vapor mingled with spray which hung over the surface of the ocean.\ \ }{1}

\end{document}

Cicada
  • 10,129