3 # :Copyright: © 2018 Günter Milde.
4 # Released without warranty under the terms of the
5 # GNU General Public License (v. 2 or later)
12 # Funktionen, die einen Trennstil (oder einen Aspekt eines Trennstils)
13 # implementieren, z.B.
15 # >>> from stilfilter import syllabisch, morphemisch
16 # >>> print(syllabisch("Pä-d<a-go-gik"))
18 # >>> print(morphemisch("Pä-d<a-go-gik"))
25 """Filter für Trennstile
27 Siehe dokumentation/Trennstile.txt.
39 # Alternativtrennungen in Fremdwörtern nach §112 und §113.
41 # _waehle_fremdwortsilben()
42 # ~~~~~~~~~~~~~~~~~~~~~~~~~
44 # Bei Konsonantenclustern mit l, n oder r wähle Trennung nach Herkunft.
46 # Regelwerk (1996) § 112:
47 # In Fremdwörtern können die Verbindungen aus Buchstaben für einen
48 # Konsonanten + l, n oder r entweder entsprechend § 110 getrennt werden,
49 # oder sie kommen ungetrennt auf die neue Zeile.
51 # >>> from stilfilter import _waehle_fremdwortsilben
52 # >>> fremdwoerter = ('no-b-le Zy-k-lus Ma-g-net Fe-b-ru-ar '
53 # ... 'Hy-d-rant Ar-th-ri-tis ge-r<i-a-t-risch '
54 # ... 'A·p-ri-ko-se Eth-ni-en')
55 # >>> for wort in fremdwoerter.split():
56 # ... print(wort, '->', _waehle_fremdwortsilben(wort))
60 # Fe-b-ru-ar -> Fe-bru-ar
61 # Hy-d-rant -> Hy-drant
62 # Ar-th-ri-tis -> Ar-thri-tis
63 # ge-r<i-a-t-risch -> ge-r<i-a-trisch
64 # A·p-ri-ko-se -> A·pri-ko-se
65 # Eth-ni-en -> Eth-ni-en
69 def _waehle_fremdwortsilben(wort
):
70 """"fremdländische" Sprechsilben (no-ble, Hy-drant, Ma-gnet)."""
71 return re
.sub('([-·])([bcdfgkptv]|th)-(?=[lrn])', '\\1\\2', wort
) # K86, K87
74 # _waehle_standardsilben()
75 # ~~~~~~~~~~~~~~~~~~~~~~~~
77 # Bei Konsonantenclustern mit l, n oder r wähle Trennung nach deutschen Regeln.
79 # >>> from stilfilter import _waehle_standardsilben
80 # >>> for wort in fremdwoerter.split():
81 # ... print(wort, '->', _waehle_standardsilben(wort))
85 # Fe-b-ru-ar -> Feb-ru-ar
86 # Hy-d-rant -> Hyd-rant
87 # Ar-th-ri-tis -> Arth-ri-tis
88 # ge-r<i-a-t-risch -> ge-r<i-at-risch
89 # A·p-ri-ko-se -> Ap-ri-ko-se
90 # Eth-ni-en -> Eth-ni-en
94 def _waehle_standardsilben(wort
):
95 """Standard-Sprechsilbentrennung (nob-le, Hyd-rant, Mag-net)."""
96 return re
.sub('[-·]([bcdfgkptv]|th)-(?=[lrn])', '\\1-', wort
) # §112
100 # K86 Untrennbar sind in Fremdwörtern die Verbindungen von Verschluß- und
101 # Reibelauten mit l und r, ...
103 # >>> fremdwoerter = ('Pu-b-li-kum flexi-b-ler Zy-k-lone Qua-d-rat '
104 # ... 'Spek-t-rum manö-v-rieren')
105 # >>> for wort in fremdwoerter.split():
106 # ... print(wort, '->', _waehle_fremdwortsilben(wort))
107 # Pu-b-li-kum -> Pu-bli-kum
108 # flexi-b-ler -> flexi-bler
109 # Zy-k-lone -> Zy-klone
110 # Qua-d-rat -> Qua-drat
111 # Spek-t-rum -> Spek-trum
112 # manö-v-rieren -> manö-vrieren
116 # >>> fremdwoerter = 'Di<s-t-rikt Ma-gis-t-rat la-kus-t-risch'
117 # >>> for wort in fremdwoerter.split():
118 # ... print(wort, '->', _waehle_fremdwortsilben(wort))
119 # Di<s-t-rikt -> Di<s-trikt
120 # Ma-gis-t-rat -> Ma-gis-trat
121 # la-kus-t-risch -> la-kus-trisch
123 # K 87 Untrennbar ist die Konsonantenverbindung "gn".
125 # >>> fremdwoerter = 'Ma-g-net Pro-g-nose Si-g-net'
126 # >>> for wort in fremdwoerter.split():
127 # ... print(wort, '->', _waehle_fremdwortsilben(wort))
128 # Ma-g-net -> Ma-gnet
129 # Pro-g-nose -> Pro-gnose
130 # Si-g-net -> Si-gnet
132 # Keine Übergeneralisierung:
134 # >>> woerter = 'Seg-ler bast-le Ad-ler'
135 # >>> for wort in woerter.split():
136 # ... print(wort, '->', _waehle_fremdwortsilben(wort))
141 # Mit Auszeichnung der "Randtrennstelle":
142 # >>> woerter = 'A·p-ri-kose i·g-no-rie-ren'
143 # >>> for wort in woerter.split():
144 # ... print(wort, '->', _waehle_fremdwortsilben(wort))
145 # A·p-ri-kose -> A·pri-kose
146 # i·g-no-rie-ren -> i·gno-rie-ren
151 # Mit regelsilben() werden alle Fremdwortsilbentrennungen nach §112 erkannt
152 # und zu Regelsilben gewandelt:
154 # >>> from stilfilter import regelsilben
155 # >>> fremdwoerter = ('no-ble Zy-klus Ma-gnet Fe-bru-ar '
156 # ... 'Hy-drant Ar-thri-tis ge-r<i-a-trisch '
158 # >>> for wort in fremdwoerter.split():
159 # ... print(wort, '->', regelsilben(wort))
163 # Fe-bru-ar -> Feb-ru-ar
164 # Hy-drant -> Hyd-rant
165 # Ar-thri-tis -> Arth-ri-tis
166 # ge-r<i-a-trisch -> ge-r<i-at-risch
167 # A·pri-ko-se -> Ap-ri-ko-se
171 def regelsilben(wort
):
172 """Regel-Sprechsilbentrennung (nob-le, Hyd-rant, Mag-net)."""
173 wort
= re
.sub('[-·]([bcdfgkptv]|th)(?=[lr][aeiouäöü])', '\\1-', wort
)
174 wort
= re
.sub('[-·]gn(?=[aeiouäöü])', 'g-n', wort
)
178 """Regelsilben bei gn (Si-gnal -> Sig-nal)."""
179 return re
.sub('[-·]gn(?=[aeiouäöü])', 'g-n', wort
)
185 # Entferne Alternativtrennungen nach §113 (verblasste Morphologie).
187 # Regelwerk (1996) §113:
188 # Wörter, die sprachhistorisch oder von der Herkunftssprache her gesehen
189 # Zusammensetzungen oder Präfigierungen sind, aber nicht mehr als solche
190 # empfunden oder erkannt werden, kann man entweder nach § 108 oder nach
191 # § 109 bis § 112 trennen.
193 # >>> from stilfilter import morphemisch
194 # >>> blasse = ('hi-n<auf wo-r=um Chry-s<an-the-me Hek-t<ar '
195 # ... 'He-li-ko<p-ter in-te-r<es-sant Li-n<oleum Pä-d<a-go-gik '
196 # ... 'au-to<ch-ton Psy-ch<i.a-trie '
197 # ... 'A<·s-phalt E·x<a-men Di-a<g-no-se A<·s-the-n=o-pie')
198 # >>> for wort in blasse.split():
199 # ... print(wort, '->', morphemisch(wort))
200 # hi-n<auf -> hin<auf
202 # Chry-s<an-the-me -> Chrys<an-the-me
203 # Hek-t<ar -> Hekt<ar
204 # He-li-ko<p-ter -> He-li-ko<pter
205 # in-te-r<es-sant -> in-ter<es-sant
206 # Li-n<oleum -> Lin<oleum
207 # Pä-d<a-go-gik -> Päd<a·go-gik
208 # au-to<ch-ton -> au-to<chton
209 # Psy-ch<i.a-trie -> Psych<i·a-trie
210 # A<·s-phalt -> A<·sphalt
211 # E·x<a-men -> Ex<a·men
212 # Di-a<g-no-se -> Di·a<gno-se
213 # A<·s-the-n=o-pie -> A<·sthen=o·pie
215 # Ersetze, wenn zwischen Haupttrennstelle und Nebentrennstelle nur ein
217 # (Die Haupttrennstelle kann vor oder nach der Nebentrennstelle liegen.)
220 def morphemisch(wort
):
221 """Bei Alternativen, Trennung nach Morphologie (hin<auf, Päd<ago-ge).
223 Entferne Alternativtrennungen nach §113 (verblasste Morphologie).
225 # nach (mit Selbstlaut):
226 wort
= re
.sub('([<=]+[.·]*[aeiouyäöü])[-.]+', '\\1·', wort
)
228 wort
= re
.sub('([<=]+[.·]*(.|ch))[-.]+', '\\1', wort
)
229 # vor (mit Selbstlaut):
230 wort
= re
.sub('[-.]+([aeiouyäöü][<=]+)', '·\\1', wort
)
232 wort
= re
.sub('[-.]+((.|ch)[<=]+)', '\\1', wort
)
233 # vor (mit Randtrennung: E·x<a-men, Di·a<g-no-se)
234 wort
= re
.sub('·(([^aeiouyäöü]|ch)[<=]+)', '\\1', wort
)
240 # >>> from stilfilter import syllabisch
241 # >>> for wort in blasse.split():
242 # ... print(wort, '->', syllabisch(wort))
243 # hi-n<auf -> hi-nauf
245 # Chry-s<an-the-me -> Chry-san-the-me
246 # Hek-t<ar -> Hek-tar
247 # He-li-ko<p-ter -> He-li-kop-ter
248 # in-te-r<es-sant -> in-te-res-sant
249 # Li-n<oleum -> Li-noleum
250 # Pä-d<a-go-gik -> Pä-da-go-gik
251 # au-to<ch-ton -> au-toch-ton
252 # Psy-ch<i.a-trie -> Psy-chi.a-trie
253 # A<·s-phalt -> As-phalt
254 # E·x<a-men -> E·xa-men
255 # Di-a<g-no-se -> Di-ag-no-se
256 # A<·s-the-n=o-pie -> As-the-no-pie
260 def syllabisch(wort
):
261 """Ignoriere "verblasste" Morphologie (hi-nauf, Hek-tar, Pä-da-go-ge)."""
263 wort
= re
.sub('[<=]+[.·]*((.|ch)[-.]+)', '\\1', wort
)
265 wort
= re
.sub('([-.]+.)[<=]+[.]*', '\\1', wort
)
271 # K44 „ſ“ (langes s) steht in Fremdwörtern...
273 # >>> blasse = ('tran<s-pirieren tran<s-zendent ab<s-tinent '
274 # ... 'Ab<s-zess Pro-s<odie')
275 # >>> for wort in blasse.split():
276 # ... print(wort, '->', morphemisch(wort))
277 # tran<s-pirieren -> tran<spirieren
278 # tran<s-zendent -> tran<szendent
279 # ab<s-tinent -> ab<stinent
280 # Ab<s-zess -> Ab<szess
281 # Pro-s<odie -> Pros<odie
283 # Trennstellen können als ungünstig markiert sein:
285 # >>> blasse = ('Bür-ger=in<.i-ti-a-ti-ve Pä-..d<e-..rast')
286 # >>> for wort in blasse.split():
287 # ... print(wort, '->', morphemisch(wort))
288 # Bür-ger=in<.i-ti-a-ti-ve -> Bür-ger=in<.i·ti-a-ti-ve
289 # Pä-..d<e-..rast -> Päd<e·rast
290 # >>> for wort in blasse.split():
291 # ... print(wort, '->', syllabisch(wort))
292 # Bür-ger=in<.i-ti-a-ti-ve -> Bür-ger=ini-ti-a-ti-ve
293 # Pä-..d<e-..rast -> Pä-..de-..rast
295 # Suffixe mit Vokalcluster nicht ändern:
297 # >>> morphemisch('Zy-klo>i-de')
304 # Unterdrücken/Zulassen von regelkonformen Trennungen je nach Anwendungsfall.
305 # (Siehe Trennstile in sprachauszug.py.)
310 # Entferne Randtrennstellen und explizit als ungünstig gekennzeichnete
311 # Trennstellen. Das Argument `level` bezeichnetwird die Zahl der
312 # Ungünstigmarker (Punkte) ab der eine Trennstelle entfernt wird.
314 # >>> from stilfilter import _unguenstig
315 # >>> _unguenstig('Text=il<..lu-stra-ti.on')
316 # 'Text=illu-stra-ti.on'
317 # >>> _unguenstig('Text=il<..lu-stra-ti.on', level=2)
318 # 'Text=illu-stra-ti.on'
319 # >>> _unguenstig('Text=il<..lu-stra-ti.on', level=3)
320 # 'Text=il<..lu-stra-ti.on'
321 # >>> print(_unguenstig('A·dress=er<.hö-hung'))
323 # >>> print(_unguenstig('A·dress=er<.hö-hung', level=0))
328 def _unguenstig(wort
, level
=1):
329 """Entferne ungünstige und Randtrennstellen ab `level`."""
330 wort
= re
.sub('[=<>]*·', '', wort
)
332 marker
= r
'\.' * level
333 wort
= re
.sub('[-=<>]+%s+'%marker
, '', wort
)
334 # TODO: einzelne Punkte (Schwankungsfälle)
335 # wort = wort.replace('.', '-')
340 # Standardunterdrückung + keine Flattervokale::
343 """Entferne ungünstige Trennungen und Einvokalsilben."""
344 return keine_flattervokale(_unguenstig(wort
))
348 # Aussortieren sehr ungünstiger (mit „..“ markierter) Trennstellen.
352 """Aussortieren sehr ungünstiger (mit „..“ markierter) Trennstellen."""
353 return _unguenstig(wort
, level
=2)
359 """Zulassen aller Trennungen (auch ungünstige) außer Randtrennungen."""
360 return _unguenstig(wort
, level
=0)
362 # _add_randtrennung()
363 # ~~~~~~~~~~~~~~~~~~~
365 # Füge Trennmöglichkeiten am Wortanfang und -ende zu, die nach §107 E2
366 # des Regelwerkes (vorher K79) verboten sind aber in Gesangstexten gebraucht
369 # >>> from stilfilter import _add_randtrennung
370 # >>> print(_add_randtrennung('Abend'))
372 # >>> print(_add_randtrennung('Ra-dio'))
375 # Das gleiche gilt für Trennmöglichkeiten am Anfang/Ende von Teilwörtern:
377 # >>> print(_add_randtrennung('Eis=ano-ma-lie'))
379 # >>> print(_add_randtrennung('Ra-dio<phon'), _add_randtrennung('Dia<gramm'))
380 # Ra-di·o<phon Di·a<gramm
382 # Ausnahmen müssen im Quelltext gekennzeichnet werden:
384 # >>> print(_add_randtrennung('Ai-chin-ger'), _add_randtrennung('Ai-da'))
386 # >>> print(_add_randtrennung('Ai-chin-ger'), _add_randtrennung('A·i-da'))
391 def _add_randtrennung(word
):
392 """Zusätzliche Trennmöglichkeiten am Wortrand (Fei-er=a·bend, Zo·o<lo-ge)."""
394 # Führender Vokal, gefolgt von Silbenanfang
395 # (optionaler Konsonant (auch ch/ck/ph/rh/sch/sh/th) + Vokal)::
397 for match
in re
.finditer(
398 '(^|[<=])([aeiouäöüAEIOUÄÖÜ])'
399 '(([^·]|ch|ck|ph|sch|st|th|[bdfgkpt][rl]|[gmp]n|sb|sk|sp|sph)?'
400 '[aeiouyäöü])', word
):
402 # Ausnahmen: Doppellaute, Diphthonge, Umlaute::
404 if re
.search('(aa|ae|ai|au|äu|ei|eu|oe|oo|ou|ue)',
405 match
.group(0), flags
=re
.IGNORECASE
):
410 word
= ''.join((word
[:match
.start()], match
.expand('\\1\\2·\\3'),
411 _add_randtrennung(word
[match
.end():])))
414 # zwei Vokale am Wortende::
416 for match
in re
.finditer('([aeiouäöü])([aeiouäöü])([<>=]|$)', word
):
417 # if 'ie' in match.group(0) and re.search('([a]-nie)', word, flags=re.IGNORECASE):
418 # sys.stderr.write(word+' '+match.group(0)+'\n')
420 # Ausnahme: Doppellaute, Diphtonge, Umlaute::
422 if re
.search('(aa|ae|ai|au|äu|ee|ei|eu|ie|oe|oi|oo|ou|ue|ui)',
428 word
= ''.join((word
[:match
.start()], match
.expand('\\1·\\2\\3'),
429 _add_randtrennung(word
[match
.end():])))
436 # mehrere Konsonanten nach Anfangsvokal
437 # >>> sample = 'Achim Acker Apha-sie Asche Osten'
439 # Wahltrennung nach §112 oder §113
440 # >>> sample += 'Adria Agnes Agro<nom Akro-nym Apri-kose Asbest Aspekt Asphalt'
441 # >>> sample += ' Eklat Etrus-ker igno-riert Okla-ho-ma ukra.i-nisch'
442 # >>> for word in sample.split():
443 # ... print(_add_randtrennung(word))
465 # Zusätzliche Trennmöglichkeiten am Wortanfang und -ende behalten,
466 # Trennungen zwischen (Halb-)Vokalen im Schwankungsfall unterdrücken.
468 # >>> from stilfilter import gesangstext
469 # >>> for wort in "A<·sphalt O·bo·e ab<a·xi.al Gli·a=zel-le".split():
470 # ... print(gesangstext(wort))
478 def gesangstext(wort
):
479 """Trennungen für Gesangstext:
480 Randtrennungen behalten, Schwankungsfälle unterdrücken.
482 wort
= wort
.replace('·', '-').replace('<-', '<')
483 wort
= re
.sub('([aeiouyäöü])\\.([aeiouyäöü])', '\\1\\2', wort
)
487 # keine_flattervokale()
488 # ~~~~~~~~~~~~~~~~~~~~~
490 # Traditionell enthalten die TeX-Trennmuster keine Trennstellen deren
491 # Abstand zur Nachbartrennstelle einen Buchstaben beträgt. Die Entscheidung
492 # „Flatterbuchstaben“ zu vermeiden folgt der Praxis im Wörterverzeichnis
493 # des „Einheitsdudens“ (Duden 1991) und Wahrig (1980).
495 # Bei einvokalischen Silben im Wortinneren, nimm die zweite:
497 # >>> from stilfilter import keine_flattervokale
498 # >>> einzelne = ('The-a-ter ge-ni.a-le')
499 # >>> for wort in einzelne.split():
500 # ... print(wort, '->', keine_flattervokale(wort))
501 # The-a-ter -> Thea-ter
502 # ge-ni.a-le -> ge-nia-le
504 # Allerdings nicht, wenn die zweite Trennstelle unterdrückt oder die erste
505 # eine Suffixtrennstelle ist:
507 # >>> einzelne = ('La-sal-le-a-.ner Athe>i-sten An<woh-ner=in<.i-ti-a-ti-ve')
508 # >>> for wort in einzelne.split():
509 # ... print(wort, '->', keine_flattervokale(wort))
510 # La-sal-le-a-.ner -> La-sal-le-a-.ner
511 # Athe>i-sten -> Athe>isten
512 # An<woh-ner=in<.i-ti-a-ti-ve -> An<woh-ner=in<.i-tia-ti-ve
516 def keine_flattervokale(wort
):
517 """Entferne Trennmarker vor Einzevokalsilben (Thea-ter)."""
518 wort
= re
.sub('>([aeiouyäöü])[-]\.?', '>\\1', wort
)
519 wort
= re
.sub('(?<![<>=])[-.]+([aeiouyäöüëï])(?=[->][^.])', '\\1', wort
)
526 # „Es gilt als Buchdruckerregel, dass zwei Buchstaben am Wortende nur im
527 # Notfall abgetrennt werden“ (Duden 1934):
529 # >>> from stilfilter import righthyphenmin3
530 # >>> sample = 'fo-to<gra-fie-re Fe-ri-en=kurs'
531 # >>> sample += ' dar<an dar<an=mach-te'
532 # >>> sample += ' aben-teu-er>li-che hu-ma-no>id Amy-lo>id=er<kran-kung'
533 # >>> sample += ' il--le-gal an-ti<zi-pier-te'
534 # >>> for word in sample.split():
535 # ... print(righthyphenmin3(word))
542 # Amy-loid=er<kran-kung
548 def righthyphenmin3(wort
):
549 # -, < und > am Schluss und vor =
550 wort
= re
.sub('[-<>.]+(..$|..=)', '\\1', wort
)
552 wort
= re
.sub('[-.]+(..[<>])', '\\1', wort
)
558 # Keine Trennung nach nur 2 Buchstaben am Wortanfang oder -ende.
561 # morphemische oder günstige Trennung am Wortanfang
562 # (z.B. Ab<bruch, Ei=sa-lat, il--le-gal):
564 # >>> from stilfilter import hyphenmin3
565 # >>> sample += ' Ab<druck=er<.laub>nis-se ab<er<.kannt un<=ge<recht=fer-tigt'
566 # >>> sample += ' be<ru-fen ab<be<ru-fen ab=zu=be<ru-fen'
567 # >>> sample += ' zu=zu=be<rei-ten un<zu<ver<läs-sig'
568 # >>> for word in sample.split():
569 # ... print(hyphenmin3(word))
576 # Amy-loid=erkran-kung
579 # Ab<druck=erlaub>nisse
581 # un<=gerecht=fer-tigt
590 def hyphenmin3(wort
):
591 """Entferne Trennungen im Abstand 2 vom Wortrand.
593 Wie \\lefthyphenmin = \\righthyphenmin = 3, aber auch in Komposita
594 und nicht bei "guten" Trennungen am Wortanfang.
596 # -, < und > am Schluss und vor =
597 wort
= re
.sub('[-<>.]+(..$|..=)', '\\1', wort
)
599 wort
= re
.sub('^(..)[->.][.]*([^-])', '\\1\\2', wort
)
601 wort
= re
.sub('(=..)[-<>.]+', '\\1', wort
)
603 wort
= re
.sub('[-.]+(..[<>])', '\\1', wort
)
605 wort
= re
.sub('([<>]..)[-.]+', '\\1', wort
)
606 # < nach < (zuerst letztes von 3)
607 wort
= re
.sub('<(..<..)[<.]+', '<\\1', wort
)
608 wort
= re
.sub('<(..)[<.]+', '<\\1', wort
)
615 # Entferne alle syllabischen Trennstellen, behalte Trennstellen an Wortfugen,
616 # nach Präfix und vor Suffix.
617 # (Entspricht in etwa dem Make-Ziel "major".)
619 # >>> from stilfilter import morphemgrenzen
620 # >>> for word in sample.split():
621 # ... print(morphemgrenzen(word))
628 # Amylo>id=er<krankung
631 # Ab<druck=er<.laub>nisse
633 # un<=ge<recht=fertigt
640 # Anwendung: Ligaturaufbruch, Tests
643 def morphemgrenzen(wort
):
644 """Entferne syllabische Trennstellen."""
646 wort
= re
.sub('[=<>]*·', '', wort
)
647 # syllabische Trennungen
648 wort
= re
.sub('-+[.]*', '', wort
)
649 # Schwankungsfälle (einzelner Punkt)
650 wort
= re
.sub('(?<![<=>·])\\.+', '', wort
)
656 # Nur Trennstellen an Wortfugen und nach Präfix.
658 # >>> from stilfilter import haupttrennstellen
659 # >>> print(haupttrennstellen('Ü·ber<=licht=ge<schwin-dig>keit'))
660 # Über<=licht=ge<schwindigkeit
662 # Anwendung: Wortanalyse, Tests
665 def haupttrennstellen(wort
):
666 """Entferne Trennstellen außer an Wortfugen und nach Präfix."""
668 wort
= re
.sub('[=<>]*·', '', wort
)
669 # syllabische Trennungen und Suffixe
670 wort
= re
.sub('[->]+', '', wort
)
671 # Schwankungsfälle und ungünstige entfernte Trennung (einzelner Punkt)
672 wort
= re
.sub('(?<![<=·])\\.+', '', wort
)
678 # Ersetze die Trennstellenauszeichnung durch ein einfaches Trennzeichen.
680 # >>> from stilfilter import einfach
681 # >>> print(einfach('Rah-men=ver<ein>ba-rung'), einfach('Re<gis-ter=ari·e'))
682 # Rah-men-ver-ein-ba-rung Re-gis-ter-ari-e
683 # >>> print(einfach('Ab<fa{ll/ll=l}a-ger'), einfach('Dru{ck/k-k}er'))
684 # Ab-falla-ger Drucker
685 # >>> print(einfach('An-ti<=geld=wä-sche===vor<rich-tung'))
686 # An-ti-geld-wä-sche-vor-rich-tung
688 # Das Argument `alternative` beschreibt die Auflösung von Mehrdeutigkeiten:
689 # 1: erste Alternative, 2: zweite Alternative, 0 ungetrennt:
691 # >>> print(einfach('Au-ssen=ma[-s/s-]se'), einfach('An-dro[/>]id'))
692 # Au-ssen-masse An-droid
693 # >>> print(einfach('Au-ssen=ma[-s/s-]se', 1), einfach('An-dro[/>]id', 1))
694 # Au-ssen-ma-sse An-droid
695 # >>> print(einfach('Au-ssen=ma[-s/s-]se', 2), einfach('An-dro[/>]id', 2))
696 # Au-ssen-mas-se An-dro-id
698 # >>> print(einfach('auf<fangen', symbol='"|'))
703 def einfach(wort
, alternative
=0 , symbol
='-'):
704 """Vereinheitliche Trennstellenmarker."""
706 # Spezielle Trennungen für die traditionelle Rechtschreibung
707 # (siehe ../../dokumente/README.wortliste)::
710 wort
= wort
.replace('{ck/k-k}', 'ck')
711 # Konsonanthäufungen an Wortfuge: '{xx/xxx}' -> 'xx':
712 wort
= re
.sub(r
'\{(.*)/.*}', r
'\1', wort
)
714 # Trennstellen in doppeldeutigen Wörtern. `alternative` wählt
715 # 1: erste Alternative, 2: zweite Alternative, 0 ungetrennt ::
719 wort
= re
.sub(r
'\[(.*)/(.*)]', r
'\%s'%str
(alternative
), wort
)
721 match
= re
.search(r
'\[(.*)/.*]', wort
)
722 kompromiss
= re
.sub('[-=<>.·]', '', match
.group(1))
723 wort
= wort
.replace(match
.group(0), kompromiss
)
725 # Trennstellen aller Kategorien::
727 wort
= re
.sub('[-=<>.·]+', symbol
, wort
)
737 if __name__
== '__main__':
741 from wortliste
import WordEntry
, ShortEntry
, filelines
, run_filters
749 parser
= argparse
.ArgumentParser(description
= __doc__
,
750 formatter_class
=argparse
.RawDescriptionHelpFormatter
)
751 parser
.add_argument('INFILES', nargs
='*', default
=['-'],
752 help='Eingabedatei(en), Default: - (Standardeingabe).')
753 parser
.add_argument('--stilliste', action
="store_true",
754 help='Beschreibung der unterstützten Trennstile')
755 parser
.add_argument('-k', '--kurzformat', action
="store_true",
756 help='Input ist Wortliste im Kurzformat. '
757 '(Default: Langformat)', default
=False)
758 parser
.add_argument('-s', '--stil', metavar
='STIL,[STIL...]',
759 help='Trennstil(e) (siehe --stilliste für Auswahl)',
761 parser
.add_argument('--test-filter', action
='store_true',
762 help='Schreibe nur geänderte Einträge.')
763 parser
.add_argument('--output-filter', metavar
='EXP',
764 help='Schreibe nur Einträge, die auf den regulären '
765 'Ausdruck EXP passen')
766 parser
.add_argument('-1', '--test-1er', action
='store_true',
767 help='Schreibe nur Einträge mit „Flattertrennung“. '
768 'Überschreibt --output-filter.')
770 args
= parser
.parse_args()
777 entry_class
= ShortEntry
780 entry_class
= WordEntry
783 if args
.output_filter
:
784 output_regexp
= args
.output_filter
788 # Keine Ausgabe, wenn alle "Flatterbuchstaben" entfernt
789 # (überschreibt "--output-filter")::
792 output_regexp
= '[-<>=.][^-<>=./][-<>=.]'
795 # Iteration über Eingabe
796 # """"""""""""""""""""""
800 for line
in filelines(args
.INFILES
or '-'):
802 # Zeile lesen und in WordEntry oder ShortEntry Objekt wandeln::
804 if not line
or line
.startswith('#'):
806 entry
= entry_class(line
)
808 # Iteration über die Felder des Eintrags::
811 for i
in range(start
,len(entry
)):
816 # Trennstil (Filter anwenden)::
818 entry
[i
] = run_filters(args
.stil
.split(','), word
)
822 # für Testzwecke: nur Worte ausgeben, die durch Filter geändert wurden::
824 if not changed
and args
.test_filter
:
827 out_line
= str(entry
)
829 # Nur Worte ausgeben, die auf den Ausgabefilter-Ausdruck passen::
831 if output_regexp
and not re
.search(output_regexp
, out_line
):
834 # Auf Standardausgabe ausgeben::