13

I need to type parallel text on facing pages (original text on right page and translation on left one) in ConTeXt. I've used ledpar in Latex but wasn't satisfied with the results (text is aligned on a paragraphs leaving blanks if one of the texts is longer than the other, a common situation). Now I would like to try it in Context. Ideally both paragraphs will have same height, I suppose changing interlinear space, etc.)

1
  • 3
    Text streams aren’t fully implemented in MkIV yet. There’s some code that does the collecting part but none for parallel output. It’s not easy to do the latter yourself because of the complex page model. Btw. ask on the mailing list so Hans knows there’s another user who would like to have it. May 12, 2013 at 21:10

1 Answer 1

9

As of August 2013 the state of Context’s text stream capability is still unsatisfying. This is especially true of the implementation in MkIV which is quite rudimentary. However, legacy Context (MkII, the format loaded when running texexec) does offer a functional, albeit a little limited streams mechanism.

MkII

In MkII you can achieve something like this quite easily:

MkII streams demo

(The horrible badness is due to very short line lengths.)

The code behind this employs the streams module that is part of Context to typeset a couple pages of bilingual text in parallel: The original, in Greek, on verso pages with the Latin translation facing it. Note that Context automatically reserves some extra space after the first paragraph on the left hand page since the original is shorter. The next paragraph then continues evenly on both sides.

What you have to do is, in essence, partition the two input texts into chunks that should be placed in parallel. At the start of each section switch to the desired page with \enableoutputstream [left] or \enableoutputstream [right], respectively, calling \synchronizeoutputstreams [...,...] when the chunk is done:

\enableoutputstream [left]
    ... text that goes on verso pages, e.g. the original

\enableoutputstream [right]
    ... text that goes on recto pages, e.g. a translation

%% stop collecting content
\enableoutputstream [default]

%% set synchronization point
\synchronizeoutputstreams [left, right] %% 

%% next chunk:
\enableoutputstream [left]
... repeat for as long as you wish

%% after you’re done, finalize:
\enableoutputstream [default]               %% stop
\synchronizeoutputstreams [left,right]      %% sync
\flushoutputstreampages [left,right]        %% flush

This means that the input file must contain both texts in interleaved order, so depending on your setup you will have to write a script that arranges it for you.

Below listing contains the full code for the example (for convenience, here’s a gist of the code):

%% first a couple global settings
\setuppapersize [A7]
\enableregime [utf]
\setuptolerance [verytolerant,stretch] %% small page sizes ...
\setupbodyfont [10pt]

\usemodule [ancientgreek]
\setupheader [style=\tfx]

\setuppagenumbering [location=,state=start,alternative=doublesided]

%% now we define a couple wrappers for the streams macros

\usemodule [streams] %% m-streams.tex

%% 1) main environment for parallel typesetting
%%    sets up running headers and ensures we begin verso

\def\startparallel {
  \page [left]
  \setupheadertexts
    %% recto
    [M. Tulli Ciceronis Timæus]
    [pagenumber]
    %% verso
    [pagenumber]
    [\localgreek{Πλάτωνος Τίμαιος}]
  \enableoutputstream [default]%
}

%% 2) last pending stream content needs to be flushed on exit

\def\stopparallel {%
  \enableoutputstream [default]%
  \synchronizeoutputstreams [left,right]%
  \flushoutputstreampages [left,right]%
}

%% 3) environment for Greek text on verso pages

\def \startplato {%% put Timaios on verso pages
  \startgreek
  \enableoutputstream [default]%
  \synchronizeoutputstreams [left,right]%
  \enableoutputstream [left]%
}

\let \stopplato \stopgreek

%% 4) environment for Latin text on recto pages

\def \startcicero {%% recto
  \bgroup
  \language [la]%
  \enableoutputstream [right]%
}

\let \stopcicero \egroup

%% helper for typesetting pagination info consistently

\define[1]\pagination{\ifhmode\hskip\emwidth\fi{\rm[#1]}\hskip\emwidth}

%% ····································································
%%                           demonstration
%% ····································································

\starttext

\startparallel

\startplato
  \pagination {27δ}
  τί τὸ ὂν ἀεί, γένεσιν δὲ οὐκ ἔχον, καὶ τί τὸ γιγνόμενον μὲν
  \pagination{28α}
  ἀεί, ὂν δὲ οὐδέποτε; τὸ μὲν δὴ νοήσει μετὰ λόγου περιληπτόν, ἀεὶ
  κατὰ ταὐτὰ ὄν, τὸ δ᾽ αὖ δόξῃ μετ᾽ αἰσθήσεως ἀλόγου δοξαστόν, γιγνόμενον
  καὶ ἀπολλύμενον, ὄντως δὲ οὐδέποτε ὄν.
\stopplato

\startcicero
  \pagination {3}
  Quid est, quod semper sit neque ullum habeat ortum, et quod gignatur
  nec umquam sit?
  Quorum alterum intellegentia et ratione conprehenditur, quod unum atque
  idem semper est; alterum, quod adfert opinionem sensus rationis
  expers, quod totum opinabile est, id gignitur et interit nec umquam
  esse uere potest.
\stopcicero

%% here the text will synchronize

\startplato
  πᾶν δὲ αὖ τὸ γιγνόμενον ὑπ᾽ αἰτίου τινὸς ἐξ ἀνάγκης γίγνεσθαι: παντὶ
  γὰρ ἀδύνατον χωρὶς αἰτίου γένεσιν σχεῖν.
  ὅτου μὲν οὖν ἂν ὁ δημιουργὸς πρὸς τὸ κατὰ ταὐτὰ ἔχον βλέπων ἀεί,
  τοιούτῳ τινὶ προσχρώμενος παραδείγματι, τὴν ἰδέαν καὶ δύναμιν αὐτοῦ
  ἀπεργάζηται, καλὸν ἐξ ἀνάγκης
  \pagination {28β}
  οὕτως ἀποτελεῖσθαι πᾶν: οὗ δ᾽ ἂν εἰς γεγονός, γεννητῷ
  παραδείγματι προσχρώμενος, οὐ καλόν.
\stopplato

\startcicero
  Omne autem, quod gignitur, ex aliqua causa gigni necesse est; nullius
  enim rei causa remota
  \pagination {4}
  reperiri origo potest.
  Quocirca si is, qui aliquod munus efficere
  molitur, eam speciem, quae semper eadem est, intuebitur atque id sibi
  proponet exemplar, praeclarum opus efficiat necesse est; sin autem eam,
  quae gignitur, numquam illam, quam expetet, pulchritudinem consequetur.
\stopcicero

%% here the text will synchronize again

\startplato
  ὁ δὴ πᾶς οὐρανὸς -- ἢ κόσμος ἢ καὶ ἄλλο ὅτι ποτὲ ὀνομαζόμενος μάλιστ᾽ ἂν
  δέχοιτο, τοῦθ᾽ ἡμῖν ὠνομάσθω -- σκεπτέον δ᾽ οὖν περὶ αὐτοῦ πρῶτον, ὅπερ
  ὑπόκειται περὶ παντὸς ἐν ἀρχῇ δεῖν σκοπεῖν, πότερον ἦν ἀεί, γενέσεως
  ἀρχὴν ἔχων οὐδεμίαν, ἢ γέγονεν, ἀπ᾽ ἀρχῆς τινος ἀρξάμενος.
  γέγονεν: ὁρατὸς γὰρ ἁπτός τέ ἐστιν καὶ σῶμα ἔχων, πάντα δὲ τὰ τοιαῦτα
  αἰσθητά, τὰ
  \pagination {28ξ}
  δ᾽ αἰσθητά, δόξῃ περιληπτὰ μετ᾽ αἰσθήσεως, γιγνόμενα καὶ γεννητὰ ἐφάνη.
  τῷ δ᾽ αὖ γενομένῳ φαμὲν ὑπ᾽ αἰτίου τινὸς ἀνάγκην εἶναι γενέσθαι.

\stopplato

\startcicero
  Omne igitur caelum siue mundus, siue quo alio uocabulo gaudet, hoc a
  nobis nuncupatus
  \pagination {5}
  sit?
  de quo id primum consideremus, quod principio est in omni
  quaestione considerandum, semperne fuerit nullo generatus ortu, an
  ortus sit ab aliquo temporis principatu.
  Ortus est, quandoquidem cernitur et tangitur et est undique corporatus.
  Omnia autem talia sensum mouent, sensusque mouentia quae sunt, eadem in
  opinatione considunt; quae ortum habere gignique diximus, nihil autem
  gigni posse sine causis.
\stopcicero

\stopparallel

\stoptext

A major restriction of this implementation is that it will work only with exactly two input streams: a left one and a right one on facing pages. The mechanism has not been designed for partitioning one or both pages into columns so as to include a third or more streams. Also, there is no option to typeset horizontally split layouts, e. g. with the original consuming the top portion (half, third, etc.) of the page and the translation occupying the bottom, nor can one of the texts be flowed into the margins. To sum up, Context MkII provides basic functionality for parallel typesetting but will not suffice for anything more demanding.

MkIV

As indicated above, the MkIV support for text streams is much less capable. Considering that it lacks the most fundamental feature -- arranging slices of text on facing pages -- I believe it justified to call it unusable. The implementation resides in page-str.lua and page-str.mkiv. This is how the MkII example looks if updated for MkIV:

MkIV misery

(Text appears to bleed into the footer for some reason.)

What MkIV can do, at the moment, is grab input from the page during the main vlist builder stage, compensate uneven chunk lengths at synchronization points, and typeset the resulting nodes. However, as this is done one stream at a time and not pagewise, the implementation lacks a method for arranging the result in a parallel manner. On the other hand, and this is somewhat promising, the new implementation handles an arbitrary number of streams, not only left and right one. Of course, in the current state this doesn’t amount to much.

The interface diverges in some respects from the legacy code. Most notably, streams that belong together are grouped inside the \startoutputstream environment of one master stream. So each chunk follows this scheme:

\startoutputstream [one] %% new master stream
        ... some text of first stream

    \enableoutputstream [two] %% slave stream
        ... text of other stream

    \synchronizestreams [one, two] %%

    %% transition to next chunk

    \enableoutputstream [one]
        ... text of first stream

    \enableoutputstream [two] %% slave stream
        ... text of other stream

    \synchronizestreams [one, two] %%

    %% repeat as necessary ...

    \disableoutputstream

\stopoutputstream %% -> closes \startoutputstream above

%% collecting is done, so here could follow some unrelated content without
%% interference

\synchronizestreams [one, two]%

%% finally, typeset what was collected

\flushoutputstream [one]%
\page
\flushoutputstream [two]%

Full listing for the example:

\setuppapersize [A7]
\setuptolerance [verytolerant,stretch] %% small page sizes ...

\setupheader [style=\tfx]

\setuppagenumbering [location=,state=start,alternative=doublesided]

\setupbodyfont [computer-modern-unicode,10pt] %% covers Greek as well

\enabletrackers[streams.flushing] %% useful debug output

%% we have to declare the streams we will use

%% 1) main environment for parallel typesetting
%%    sets up running headers and ensures we begin verso

\def\startparallel {
  \page [left]
  \setupheadertexts
    %% recto
    [M. Tulli Ciceronis Timæus]
    [pagenumber]
    %% verso
    [pagenumber]
    [{\language[agr]Πλάτωνος Τίμαιος}]
  \startoutputstream [greek]%% the reference for compensation
}

%% 2) last pending stream content needs to be flushed on exit

\def\stopparallel {%
  \disableoutputstream
  \stopoutputstream
  \synchronizestreams [greek, latin]%
  \flushoutputstream [greek]%
  \page
  \flushoutputstream [latin]%
}

%% 3) environment for Greek text on verso pages

\def \startplato {%% put Timaios on verso pages
  \bgroup
  \language [agr]%
  \synchronizestreams [greek, latin]%
  \enableoutputstream [greek]%
}

\let \stopplato \egroup

%% 4) environment for Latin text on recto pages

\def \startcicero {%% recto
  \bgroup
  \language [la]%
  \enableoutputstream [latin]%
}

\let \stopcicero \egroup

%% helper for typesetting pagination info consistently

\define[1]\pagination{\ifhmode\hskip\emwidth\fi{\rm[#1]}\hskip\emwidth}

%% ····································································
%%                           demonstration
%% ····································································

\starttext

\startparallel

\startplato
  \pagination {27δ}
  τί τὸ ὂν ἀεί, γένεσιν δὲ οὐκ ἔχον, καὶ τί τὸ γιγνόμενον μὲν
  \pagination{28α}
  ἀεί, ὂν δὲ οὐδέποτε; τὸ μὲν δὴ νοήσει μετὰ λόγου περιληπτόν, ἀεὶ
  κατὰ ταὐτὰ ὄν, τὸ δ᾽ αὖ δόξῃ μετ᾽ αἰσθήσεως ἀλόγου δοξαστόν, γιγνόμενον
  καὶ ἀπολλύμενον, ὄντως δὲ οὐδέποτε ὄν.
\stopplato

\startcicero
  \pagination {3}
  Quid est, quod semper sit neque ullum habeat ortum, et quod gignatur
  nec umquam sit?
  Quorum alterum intellegentia et ratione conprehenditur, quod unum atque
  idem semper est; alterum, quod adfert opinionem sensus rationis
  expers, quod totum opinabile est, id gignitur et interit nec umquam
  esse uere potest.
\stopcicero

%% here the text will synchronize

\startplato
  πᾶν δὲ αὖ τὸ γιγνόμενον ὑπ᾽ αἰτίου τινὸς ἐξ ἀνάγκης γίγνεσθαι: παντὶ
  γὰρ ἀδύνατον χωρὶς αἰτίου γένεσιν σχεῖν.
  ὅτου μὲν οὖν ἂν ὁ δημιουργὸς πρὸς τὸ κατὰ ταὐτὰ ἔχον βλέπων ἀεί,
  τοιούτῳ τινὶ προσχρώμενος παραδείγματι, τὴν ἰδέαν καὶ δύναμιν αὐτοῦ
  ἀπεργάζηται, καλὸν ἐξ ἀνάγκης
  \pagination {28β}
  οὕτως ἀποτελεῖσθαι πᾶν: οὗ δ᾽ ἂν εἰς γεγονός, γεννητῷ
  παραδείγματι προσχρώμενος, οὐ καλόν.
\stopplato

\startcicero
  Omne autem, quod gignitur, ex aliqua causa gigni necesse est; nullius
  enim rei causa remota
  \pagination {4}
  reperiri origo potest.
  Quocirca si is, qui aliquod munus efficere
  molitur, eam speciem, quae semper eadem est, intuebitur atque id sibi
  proponet exemplar, praeclarum opus efficiat necesse est; sin autem eam,
  quae gignitur, numquam illam, quam expetet, pulchritudinem consequetur.
\stopcicero

%% here the text will synchronize again

\startplato
  ὁ δὴ πᾶς οὐρανὸς -- ἢ κόσμος ἢ καὶ ἄλλο ὅτι ποτὲ ὀνομαζόμενος μάλιστ᾽ ἂν
  δέχοιτο, τοῦθ᾽ ἡμῖν ὠνομάσθω -- σκεπτέον δ᾽ οὖν περὶ αὐτοῦ πρῶτον, ὅπερ
  ὑπόκειται περὶ παντὸς ἐν ἀρχῇ δεῖν σκοπεῖν, πότερον ἦν ἀεί, γενέσεως
  ἀρχὴν ἔχων οὐδεμίαν, ἢ γέγονεν, ἀπ᾽ ἀρχῆς τινος ἀρξάμενος.
  γέγονεν: ὁρατὸς γὰρ ἁπτός τέ ἐστιν καὶ σῶμα ἔχων, πάντα δὲ τὰ τοιαῦτα
  αἰσθητά, τὰ
  \pagination {28ξ}
  δ᾽ αἰσθητά, δόξῃ περιληπτὰ μετ᾽ αἰσθήσεως, γιγνόμενα καὶ γεννητὰ ἐφάνη.
  τῷ δ᾽ αὖ γενομένῳ φαμὲν ὑπ᾽ αἰτίου τινὸς ἀνάγκην εἶναι γενέσθαι.

\stopplato

\startcicero
  Omne igitur caelum siue mundus, siue quo alio uocabulo gaudet, hoc a
  nobis nuncupatus
  \pagination {5}
  sit?
  de quo id primum consideremus, quod principio est in omni
  quaestione considerandum, semperne fuerit nullo generatus ortu, an
  ortus sit ab aliquo temporis principatu.
  Ortus est, quandoquidem cernitur et tangitur et est undique corporatus.
  Omnia autem talia sensum mouent, sensusque mouentia quae sunt, eadem in
  opinatione considunt; quae ortum habere gignique diximus, nihil autem
  gigni posse sine causis.
\stopcicero

\stopparallel

\stoptext

If you are a (prospective) Context user, consider it your duty to ask for full-fledged text streams in MkIV on the mailing list so Hans knows there is serious demand. There were already a couple attempts in the past but no one so far succeeded in convincing him.

3
  • 2
    Has the situation with MkIV improved since this answer was given? May 21, 2015 at 6:49
  • You can track the progress of the implementation on the git mirror. TL;DR: Not much appears to have happened. Anyways, you can always ask on the mailing list. Jun 15, 2015 at 19:56
  • Great job Philipp. Can this be done in columns instead of pages at the moment? Dec 20, 2018 at 0:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .