[Trennmuster] Alternative Trennmusterverwendung mit LuaTeX

Keno Wehr wehr at abgol.de
Fr Sep 25 22:52:26 CEST 2020


Liebe Trennfreunde,

durch die Mitarbeit am Sprachpaket polyglossia und die dort gewonnenen 
Erfahrungen mit LuaTeX und seinen „node lists“, in denen die einzelnen 
Buchstaben, Weißräume, Trennstellen, Ligaturen etc. verwaltet werden, 
ist mir aufgegangen, dass LuaTeX das Mittel der Wahl ist, um einige 
langfristige Ziele des Trennmusterprojekts zu erreichen. Dies betrifft:

 1. die Wichtung von Trennstellen nach Güte, d. h. vor allem die
    Bevorzugung von Trennungen an Wortfugen
 2. die automatische Einfügung von Spezialtrennungen der AR wie
    {ck/k-k}, {ff/ff-f}; die bisherigen Shorthands "ck, "ff usw. würden
    dann überflüssig
 3. der musterbasierte automatische Ligaturaufbruch als Ablösung des
    Shorthands "|
 4. die musterbasierte automatische Ersetzung von s durch ſ an den
    erforderlichen Stellen im Fraktursatz als Vervollkommnung der von
    Torsten Brongert im Paket blacklettert1 angewandten
    halbautomatischen Methode

Auf meine Frage nach einer Lua-Implementierung eines Trennalgorithmus 
auf der TeX-hyphen-Liste sind zwei Antworten eingegangen:

Stephan Hennig weist auf sein padrinoma-Projekt hin 
(https://github.com/sh2d/padrinoma), das erfreulicherweise weitestgehend 
meiner Intention entsprechen zu scheint und in dem offenbar bereits ein 
Großteil des benötigten Lua-Codes fertig vorliegt, ohne dass er bisher 
auf dem CTAN veröffentlicht worden wäre.

Die zweite Antwort stammt vom Babel-Betreuer Javier Bezos, der auf den 
(nur mit LuaTeX verfügbaren) Babel-Befehl \babelposthyphenation hinweist 
(https://github.com/latex3/babel/wiki/Non%E2%80%93standard-hyphenation-with-luatex). 
Soweit ich es beurteilen kann, ist dieser Befehl aber für die oben 
formulierten Ziele 1, 3 und 4 nicht mächtig genug, da kein Zugriff auf 
zusätzliche (Pseudo-)Trennmuster möglich ist. Die gewählten Beispiele im 
verlinkten Dokument legen nahe, dass der Befehl eine geeignete Lösung 
für das Ziel Nr. 2 bieten kann, aber auch da habe ich meine Zweifel. Man 
kann zwar einstellen, dass „f<Trennstelle>f“ immer „ff-f“ getrennt 
werden soll, aber ich sehe nicht, wie dabei zwischen „Schiffer“ und 
„Schiffahrt“ unterschieden werden kann.

Daher würde ich einstweilen gerne den von Stephan eingeschlagenen Weg 
fortsetzen und biete hiermit meine Mitarbeit am padrinoma-Projekt an.

Bevor es sich lohnt, am konkreten Lua-Code weiterzuarbeiten, sollten wir 
einige grundsätzliche Überlegungen zur Umsetzung anstellen.


Zu 1:
Zur Unterscheidung von Trennungen unterschiedlicher Güte sind 
verschiedene Vorgehensweisen denkbar.

Variante a)
Hier war gelegentlich der Vorschlag zu lesen, TeX solle bei 
unterschiedlichen Versuchen, einen Absatz gut zu umbrechen, 
unterschiedliche Trennmuster verwenden, wobei mit jedem Durchlauf dann 
weitere, ungünstigere Trennstellen mit in Betracht zu ziehen wären. Dies 
würde das bisherige Verfahren in gewisser Weise verallgemeinern.
TeX versucht in einem ersten Durchlauf, einen Absatz ohne Trennstellen 
zu setzen. D. Knuth begründet dies miteinem Performance-Vorteil durch 
das Einsparen des Trennalgorithmus (der mit heutiger Hardware vermutlich 
keine große Rolle mehr spielt). Es ist aber auch typographisch sinnvoll, 
da die gänzliche Abwesenheit von Worttrennungen die Lesbarkeit erhöht, 
sofern dabei nicht andere Nachteile auftreten. Wenn bei diesem Versuch 
zu viele Fehlerpunkte (demerits) auftreten, wird ein weiterer Versuch, 
den Absatz zu setzen, unternommen. Dabei werden vorher – basierend auf 
den aktivierten Trennmustern – Trennstellen in Form von penalties in den 
Text eingefügt. Der Zahlenwert der penalties, der in die Berechnung der 
Fehlerpunkte des Absatzes eingeht, ist dabei für alle Trennstellen 
gleich (\hyphenpenalty). In aller Regel wird so ein nach TeXs Maßstäben 
passabler Umbruch gefunden.Wenn das nicht der Fall ist, ragen 
möglicherweise einige Wörter in den rechten Rand. Wenn der Nutzer für 
die Länge \emergencystretch einen postiven Wert festlegt, wird in einem 
solchen Fall noch ein dritter Durchlauf unternommen, bei dem größere 
Wortzwischenräume erlaubt sind.
Eine naheliegende Umsetzung o. g. Idee wäre es, im zweiten Durchlauf 
Muster zu aktivieren, die nur die Haupttrennstellen (i. S. v. 
„Trennstile.txt“) enthalten, und nach diesem Durchlauf bei Bedarf 
weitere einzuschalten, die immer mehr Trennstellen enthalten, etwa in 
einem dritten Durchlauf auch Wortfugen der zweiten Ebene und in einem 
vierten dann alle Trennstellen oder auch noch feiner untergliedert.Der 
im Original dritte Durchlauf könnte als letzter noch hinterhergeschoben 
werden.
LuaTeX bietet einen callback namens „linebreak_filter“, der es 
ermöglicht, den Zeilenumbruchalgorithmus zu ersetzen. Hiermit müsste 
sich das beschriebene Verfahren prinzipiell umsetzen lassen. Dies wäre 
nach meiner Einschätzung allerdings ein immenser Programmieraufwand, da 
es hier um ein Herzstück von TeX geht.

Variante b)
Die Grundidee ist hier, nicht mehr alle Trennstellen gleich zu bewerten, 
sondern den penalty-Wert umso kleiner zu machen, je günstiger die 
Trennstelle ist. Dann käme man mit dem Standardumbruchalgorithmus aus 
und müsste nur das Einfügen der Trennstellen modifizieren. Hierfür gibt 
es den LuaTeX-callback „hyphenate“.
Der Vorteil gegenüber Variante a liegt aus meiner Sicht nicht nur in der 
mutmaßlich einfacheren Implementierbarkeit, sondern auch in der 
Möglichkeit, durch Berücksichtigung einer einzigen ungünstigen 
Trennstelle einen insgesamt besseren Umbruch zu erreichen, bei dem 
ansonsten nur günstige Trennstellen verwendet werden. Zu einer solchen 
Abwägung (durch Addition der verschiedenen penalty-Werte) ist der in a 
beschriebene Algorithmus nicht in der Lage, da dort innerhalb eines 
Durchlaufs alle Trennstellen gleich gewichtet werden.
Die Frage ist hier allerdings, woher die Informationen über die Güte der 
Trennstellen bezogen werden sollen. Es wäre zwar prinzipiell denkbar, 
hierfür eine neue Datenstruktur zu entwickeln, in der den Liangschen 
Mustern noch Wichtungen hinzugefügt werden, allerdings scheint mir das 
unverhältnismäßig aufwendig. Praktikabler finde ich die Analyse 
verschiedener Trennmustersätze mit Mustern steigender Anzahl an 
Trennstellen wie in Variante a beschrieben durch den Trennalgorithmus. 
Trennstellen, die in allen Mustern enthalten sind, würden dann die 
wenigsten Strafpunkte erhalten, Trennstellen, die nur in den Mustern mit 
den ungünstigsten Trennstellen enthalten sind, die meisten. Prinzipiell 
können beliebig viele Güteebenen berücksichtigt werden.

Mit ist keine Implementierung einer dieser beiden Varianten bekannt, 
aber mit dem Code aus dem padrinoma-Projekt ist der Variante b ein gutes 
Stück vorgearbeitet. Soweit ich es im Moment beurteilen kann, müsste nur 
noch der Vergleich der Trennstellen aus unterschiedlichen Mustersätzen 
und die daraus resultierende Wichtung der Trennstellen umgesetzt werden.

Ich vermute, dass drei verschiedene Güteebenen für Trennstellen in der 
Praxis für einen sehr ordentlichen Umbruch ausreichen (1. 
Haupttrennstellen 1. Art; 2. Haupttrennstellen 1. und 2. Art; 3. alle 
Trennstellen, abgesehen von den als ungünstig angesehenen, entspricht 
den bisherigen deutschen Trennmustern). Das soll natürlich nicht heißen, 
dass der Lua-Code auf drei Mustersätze beschränkt werden soll; die 
Anzahl könnte man durchaus variabel halten.
Auch wenn die Laufzeit des hier ins Auge gefassten Projekts unbestimmt 
ist, würde ich doch dafür plädieren, die Mustersätze 1 und 2 möglichst 
beim nächsten Upload der Allgemeinheit zur Verfügung zu stellen. Zwar 
gibt es noch keine offizielle Schnittstelle dafür, doch wäre es dann 
einfacher, eine solche zu schaffen, da die manuelle Installation eines 
Trennmustersatzes deutlich aufwendiger als die eines Paketes ist. Mit 
geeigneten Schnittstellen könnten solche Muster auch unabhängig von 
einem wichtenden Trennalgorithmus verwendet werden, wenn etwa 
ungünstigere Trennstellen gänzlich unberücksichtigt bleiben sollen.


Zu 2:
Die Spezialtrennungen sind im padrinoma-Projekt bereits implementiert. 
Dabei wird auf den bereits genannten LuaTeX-Callback „hyphenate“ 
zurückgegriffen, in den nach einer standardmäßigen Worttrennung die 
Spezialtrennungen eingefügt werden.
Wenn man das mit der Nr. 1 zusammensieht wird klar, dass beide Projekte 
gemeinsam implementiert werden müssen, da sie erstens den gleichen 
Callback benötigen (bei unabhängiger Implementierung würde vermutlich 
der eine Algorithmus den anderen überschreiben) und zweitens bei 
Anwendung gewichteter Trennung diese konsequenterweise auch auf die 
Spezialtrennungen ausgedehnt werden sollte.
Die Spezialtrennungen {ff/ff=f}, {mm/mm=m} usw. treten nur an Wortfugen 
auf, können aber trotzdem unterschiedliche Positionen in der 
Trennhierarchie einnehmen (Schiffahrt vs. Schiffahrtsgesellschaft).
Die Spezialtrennung {ck/k-k} tritt nie an Wortfugen auf und ist, wenn 
ich nichts übersehe, immer nur auf der untersten Stufe der Hierarchie 
möglich.
Daraus ergibt sich, dass für die Spezialtrennungen Trennmuster für 
ebenso viele Güteebenen benötigt werden wie für die Normaltrennungen, 
sodass wir nach meinem Vorschlag von drei Ebenen schon bei insgesamt 
sechs Mustersätzen für die AR sind.
Eine Vereinigung von Spezial- und Normaltrennungen in einer Musterdatei 
würde wiederum eine neue Datenstruktur erfordern ist daher als zu 
aufwendig zu verwerfen.

Mein Hauptanliegen zu dieser Thematik wäre ein Skript im 
Wortlistenrepositorium, das die Spezialtrennmuster erzeugen kann; soweit 
ich sehe, gibt es das bisher nicht.
Im padrinoma-Repositorium gibt es einen sechs Jahre alten 
Spezialtrennmustersatz: 
https://github.com/sh2d/padrinoma/blob/master/examples/patterns/hyph-de-1901-nonstd.pat.txt
Hast du zur Erzeugung ein Skript, Stephan?


Zu 3:
Für den Ligaturaufbruch liegt bereits eine vollständige Implementierung 
von Stephan im padrinoma-Projekt vor, die den LuaTeX-Callback 
„ligaturing“ nutzt. Bisher habe ich bei der Erprobung keine Fehler 
gefunden. Insbesondere funktioniert die Trennmusteranwendung (die 
eigentliche für die Silbentrennung) trotz der eingefügten 
Ligaturaufbrecher (ZWNJ), was man beispielsweise am Wort „Chefingenieur“ 
(in der Wortliste: Chef=in<.ge-nieur) sehen kann. Hier wird 
erwartungsgemäß „Chef-inge-neur“ getrennt, während man mit dem 
Babelshorthand "| (Chef"|ingenieur) zwar den korrekten Ligaturaufbruch, 
aber keine korrekte Trennung erhält (Chef-in-ge-nieur), da die Muster 
auf die Teilwörter vor und nach der Aufbruchstelle separat angewandt werden.

Die gewählte Methode hat allerdings ein anderes Problem: Es können nur 
die Aufbruchstellen berücksichtigt werden, die in der Wortliste als 
Fugen (< oder =) markiert sind. Im Duden (2006, S. 112) sind weitere 
Ligaturaufbrüche vorgesehen: »Eine Ligatur wird nur gesetzt, wenn die 
Buchstaben im Wortstamm zusammengehören.« Keine fl-Ligatur will der 
Duden in »ich schaufle« und keine ft-Ligatur in »ich kaufte« sehen.
In der Dokumentation zum nicht mehr gepflegten Skript 
„prepare-ligature-wordlist.py“ schreibt Lukas Sommer:

    * Bei den anderen Suffixen gehen die Meinungen auseinander und es
    gibt keine
    einheitliche Praxis. Dies betrifft:
         * Flexionssuffixe, die nicht mit einer Silbengrenze
    zusammenfallen: „[er]
         kauf|t“
         * Flexionssuffixe, die mit einer Silbengrenze zusammenfallen:
    „[er] kauf|te“
         * weitere Suffixe: „käuf|lich“

Auch wenn hier unterschiedliche Auffassungen existieren, sollte ein 
Paket zum Ligaturaufbruch die strittigen Ligaturen doch zumindest 
optional aufbrechen können, zumal dies vom Duden gefordert wird.
Es stellt sich allerdings die Frage, ob dies auf der Grundlage der 
Wortliste mit vertretbarem Aufwand möglich ist. Evtl. könnte man das 
grammatische Kurzformat hierfür weiterentwickeln, da die Flexionsendung 
auf dieser Grundlage als solche erkennbar wird („kaufte“ von „kaufen“, 
„schaufle“ von „schaufeln“ etc.). Verben werden zur Zeit allerdings noch 
nicht unterstützt.

Eine andere Überlegung ist, ob es überhaupt noch ein 
Ligaturaufbruchpaket braucht, da es mit selnolig bereits ein recht gutes 
gibt.
Wir könnten überlegen, das uns in der Wortliste zur Verfügung stehende 
Material zur systematischen Fehlersuche und -meldung an den 
selnolig-Betreuer statt zur Implementierung eines eigenen Pakets zu 
verwenden.


Zu 4:
Für die Rund-s-Lang-s-Ersetzung können die vorhandenen Skripte bereits 
Pseudotrennmuster erstellen. Ohne diese getestet zu haben, ist mein 
Eindruck, dass die Skripte weitgehend ausgereift sind.
Das padrinoma-Projekt kann zweifellos im Hinblick auf die Anwendung 
dieser Muster weiterentwickelt werden. Ein geeigneter LuaTeX-callback 
wäre noch zu suchen. Dabei sind die Wechselbeziehungen zu anderen oben 
genannten Prozessen im Auge zu haben. Insbesondere müsste die Ersetzung 
vor dem Ligaturalgorithmus erfolgen, da für ſ und s unterschiedliche 
Ligaturen existieren.
Außerdem stellt sich die Frage, ob für Texte mit Lang-s eigene 
Trennmuster erforderlich sind oder TeX dazu überredet werden kann, bei 
der Trennung ſ wie s zu behandeln.


Ich freue mich auf eure Meinungen und Ideen zu diesem Themenkomplex.

Schöne Grüße
Keno
-------------- nächster Teil --------------
Ein Dateianhang mit HTML-Daten wurde abgetrennt...
URL: <https://listi.jpberlin.de/pipermail/trennmuster/attachments/20200925/1c88d602/attachment.htm>


Mehr Informationen über die Mailingliste Trennmuster