[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