TeX mit Anschluß Adressensuche und -einbindung in TeX Ein nicht unbekannte Situation: Man beginnt einen Brief aufzusetzen, doch von der Anschrift haften nur Bruchstücke im Gedächtnis. TeX-Anwender können jetzt beruhigt aufatmen, schließlich ist ihr Favorit erweiterbar. Was also lag näher, als dem Satzsystem ein 'Datenbankfeature' zu liefern, genauer, LaTeX um eine Funktion zu erweitern, die es möglich macht, allein durch die Angabe der Fragmente, die von der Adresse noch bekannt sind, den Rest selbständig zusammenzusuchen. Die erste Überlegung galt den zu verwaltenden Daten, den Adressen und dem Format, in dem diese vorliegen sollen. Ich habe ein einfaches Format gewählt, somit läßt sich eine Exportsdatei aus Adimens bzw. dBase leicht einbinden. Die Adressen, also Name, Strasse, Ort und Telefon müssen zeilenweise in einer ASCII-Datei vorliegen, wobei jeder Adressenblock vom folgenden durch eine Leerzeile getrennt wird: Otto Normal Beethovenstr. 13 6100 Darmstadt 01234/56789 Karl Mustermann ... Jede Adresse muß exakt so in der Datei, wie sie später im Adressenkopf des Briefes erscheinen soll. Daher dürfen in der Datendatei keine Zeichen vorkommen, die nicht zu einer Adresse gehören. Genauso muß die Zeilenanzahl jeder Adresse konstant gehalten sein. Nicht ausgefüllte Daten sind durch Leerzeilen zu ersetzen, wie dies bei den Exportdateien üblich ist. Was Umlaute in den Adressen betrifft, so hängt dies ganz davon ab, wie solche in der vorliegenden LaTeX-Version behandelt werden. Allgemein gilt jedoch, daß man alle weiteren Sonderzeichen in bekannter LaTeX-Schreibweise einzugeben hat. Einbinden Das LaTeX-Dokument muß lediglich um den Optionsstyle 'finder' und zwei Befehle erweitert werden, um die Möglichkeiten des finder.sty nutzen zu können: \documentstyle[finder]{letter} \begin{document} \findname[]{} \addressfile{} \begin{letter}{\name \\ \street \\ \city } ... \end{letter} \end{document} Man erkennt, daß durch die Angabe eines (in geschweiften Klammern) bzw. zweier Suchworte im Makro \findname und dem anschließenden Aufruf des \addressfile-Makros mit dem zugehörigen Adreßdateinamen danach die Makros \name, \street und \city (und \telephone) zur Verfügung stehen. Bei erfolgreicher Suche enthalten diese die vollständige Adresse. In Serie Wenn das Makropaket eine Adresse finden kann, sollte es sich auch auf die Bearbeitung von Serienbriefen ausdehnen lassen. Dazu muß man lediglich einen Standardbrief, der die Variablen \name, \street und \city enthält, an das Makro \serienbrief{...} übergeben. Damit entfäält bei dieser Anwendung entfällt die Angabe von Suchwörtern. Die Datendatei wird vollständig abgearbeitet. \documentstyle[finder]{letter} \begin{document} \serienbrief{ % \begin{letter}{\name \\ \street \\ \city } ... \end{letter} } \addressfile{} \end{document} Aufspalten Nachdem der Benutzer in seinem Brief ein bzw. zwei Worte angegeben hat, kann die Suche in einer Adressendatei beginnen. Dabei wird die Datei zeilenweise von dem Makrokomplex eingelesen und Wort für Wort nach zu findenen Daten durchsucht. Im Aufspalten der Zeile in einzelne, nur durch Leerzeichen getrennte Wörter liegt das größte Problem, dessen Lösung kennzeichnet zugleich das Herzstück des finder.sty. Verlief die Suche nach den vorgegebenen Wörtern erfolgreich, wird die gefundene Adresse in Variablen verpackt und kann von dem Anwender in dessen LaTeX-Dokument weiterverarbeitet werden. Der Anfangsbereich des Styles beinhaltet neben einer Meldung alle vor dem ersten Durchlauf des Makropaketes notwendigen Grunddefinitionen. Viele der Einstellungen müssen in den Makros wiederholt werden, da es auch möglich sein soll, das Makropaket mehrmals in einem LaTeX-Dokument aufzurufen. Einmal odert immer? Der finder.sty setzt sich aus drei Makros zusammen, deren Beschreibung gemäß des Programmdurchlaufs erfolgt. Soll nach einer Adresse gesucht werden, so müssen an \findname[...]{...} ein oder (optional) zwei Suchwörter übergeben werden. \findname ist so programmiert, daß es, falls nur ein Suchwort (in geschweiften Klammern) angegeben wurde, dieses zweimal an \findn@me weiterliefert. Dort werden die Suchwörter in den Variablen \firstname und \secondname abgelegt. Beiden Makros lassen sich damit auch nach dem \findname-Aufruf im LaTeX-Dokument verwenden. Eine Kontrolle stellt sicher, daß keine Leerzeichen übergeben wurden. Danach sind alle Flags so gestellt, daß die Suche zum ersten Mal oder ggf. wieder neu beginnen kann, falls dies die zweite Adresse ist, nach der gesucht werden soll. Will man einen Serienbrief starten, so speichert das \serienbrief-Makro den übergebenen Text des Serienbriefes ab und setzt die zugehörigen Flags dementsprechend. Suche... Der erste Schritt besthet im Aufruf von \addressfile und der Angabe der zu durchsuchenden Datei. Aber auch dieses Makro ist nicht das eigentliche Ausführende, sondern es trifft nur eine Vorentscheidung. Sollen beispielsweise mehrere Dateien durch mehrmaliges Aufrufen des \addressfile-Befehls nach einer Adresse durchsucht werden und ist die Suche schon in einer der ersten Dateien erfolgreich, so hat sich das Weitersuchen in allen nachfolgenden Dateien erübrigt. Das Makro bricht in diesem Fall mit einer Bildschirmmeldung ab. Die Suche startet mit dem \analysefile-Makro, das vom \addressfile-Makro aufgerufen wird. Hier wird zuerst die Datendatei geöffnet, danach geklärt, ob eine Suche überhaupt stattfindet oder ob ein Serienbrief an alle Adressen geschrieben werden soll. Nach der Startmeldung beginnt eine Schleife. Jeder Durchlauf entspricht dem Einlesen eines Adressenblocks. Somit existieren im vorliegenden Falle vier nahezu gleiche Blöcke für \name, \street, \city und \telephone. Als fünftes schließt sich eine Zeile an, die die Leerzeile zwischen den Adressenblöcken einliest. Jeder der vier Blöcke hat drei Aufgaben. Die erste besteht im Einlesen der nächsten Datenzeile und der Übergabe an das entsprechende Makro. Darauf findet, falls keine Leerzeile eingelesen wurde, ein Weitergabe der Zeile zum Durchsuchen an das \lookat-Makro statt. Sollte jedoch eine Leerzeile eingelesen worden sein, so wird das zugehörige Makro gelöscht und mit einer entsprechenden Bildschirmmeldung versehen. Das Löschen ist unbedingt nötig, da ansonsten TeX das zugehörige Makro nicht mit einer Leerzeile, sondern mit einem \par füllt. Dies könnte beim Verwenden des Makros im LateX-Dokument unangenehme Folgen haben. Bevor ich auf die Analyse der gelesenen Zeile durch das \lookat-Makro eingehe, möchte ich die Beschreibung des Endes des \analysefile-Makros vorziehen. Die Situation am Ende der vier Blöcke unterscheidet sich durch drei Fälle: Das schlechteste Ergebnis der Suche wäre ein Mißerfolg. In diesem Fall werden zusammen mit einer entsprechenden Bildschirmmeldung die vier Adreßvariablen gelöscht. Einer erneuten Suche in einer anderen Datei steht dennoch nichts im Wege. Es muß nur ein \addressfile-Aufruf mit einer anderen Adressendatei folgen. Bei einer erfolgreichen Suche wird \stillmore auf 'false' gesetzt und damit die Suche vorzeitig abgebrochen. Das Ergebnis der Suche kommt auf dem Bildschirm zur Angezeige. Im dritten Fall, der Serienbriefanwendung, wird die gerade gelesenen Adresse auf dem Bildschirm ausgegeben und der Text des Serienbriefes an TeX weitergereicht. Die darin enthaltenen Adressenvariablen haben dabei den Inhalt der aktuellen Adresse. Am Ende des \analysefile-Makros wird dann entweder eine neue Schleife gestartet oder die Adressendatei geschlossen und das Makro beendet. ... und finden Die eigentliche Suche findet im \lookat-Makro statt. Von größter Wichtigkeit ist hierbei, daß die eingelesenen Zeile expandiert an dieses Makro übergeben wird. Daß heißt, die Zeile darf nicht in einem \line-Makro verpackt, sondern muß, wie in der Datei, explizit hinter dem \lookat-Aufruf stehen. Nun kommt es darauf an, die Zeile Wort für Wort zu zerhacken und dabei in einer bestimmten Variable immer nur ein Wort der Zeile zur Verfügung zu haben. Dieses läßt sich dann sehr einfach mit den Suchwörtern vergleichen. Eine Suche kann nur erfolgreich sein bei exakter Übereinstimmung zwischen dem in der Datedatei extrahierten und dem zu suchendem wort: Groß- und Kleinschreibung haben also durchaus Bedeutung. Die Aufgabe des Zerhackens einer Zeile und des Vergleichens mit den Suchwörtern übernimmt das rekursiv definierte \lookat-Makro. \lookat ist mit einem Leerzeichen zwischen den beiden Übergabeparametern und den drei Klammeraffen (@) danach so definiert, daß es ein bestimmtes Format von den folgenden Zeichen erwartet. #1 bekommt alle dem \lookat-Makro nachfolgenden Buchstaben bis zum ersten Leerzeichen zugewiesen; #2 erhält den Rest der Dateizeile bis zu den drei Klammeraffen, die somit als Zeilenendekennung dienen. In \lookat liegt in der \found-Variable immer ein Wort der Zeile vor. Dieses und auch alle anderen Wörter der Zeile werden Stück für Stück mit den Suchwörtern verglichen. Bei erfolgreicher Suche erhält jedes gefundene Suchwort einzeln ein Flag zugeordnet. Stehen beide Suchwörter in einem Adressenblock auf 'true' schaltet auch \foundname auf 'true'. Beim wortweisen Durchsuchen der Zeile enthält demnach \rest immer den Restbestandteil der Zeile. Dieser wird analog zur gelesenen Zeile expandiert und wieder an \lookat unter Beachtung des Formats übergeben. \found erhält nun das erste Wort vom \rest-Inhalt übergeben und der \rest-Inhalt und der Inhalt von \rest wird um dieses Wort verringert. Man erkennt, daß \lookat-Makros ruft sich selbst aufruft. Noch etwas zu der Sonderstellung der Leerzeichen in den Adressenblöcken: Da immer nur wortweise Vergleich mit den Suchwörtern erfolgt, erklärt sich von selbst, daß diese niemals ein Leerzeichen enthalten dürfen. Ansonsten wäre die Suche 100%ig erfolglos, da \found immer nur ein Wort enthält. Die Rekursion des \lookat-Makros wird entweder abgebrochen, wenn beide Suchwörter im aktuellen Adressenblock gefunden wurden oder \rest leer ist, daß heißt, die momentane Zeile ganz durchsucht wurde. Erweitern Wie ich schon erwähnt habe, wächst die anwendungsbreite des finder.sty durch Einbezug Eportdateien. Eine derartige Verknüpfung macht hat aber eine Anpassung der Ausgabevariablen \name, \street und so weiter notwendig. Selbstverständlich lassen sich die vier Makros beliebig umbenennen, gleichwohl muß bei der Einfühung weiterer Ausgabevariablen folgendes beachtet werden. Gesetzt den Fall, die Anrede der Person soll noch in die Adressenblöcke aufgenommen werden. Dazu verdoppelt man zuerst den vierten, \telephone-Block. Danach muß \linefour beispielsweise in \linefive und demzufolge \linefive in \linesix umbenannt werden. Das die Numerierung dabei stimmt, ist nicht das Wichtige, sondern, daß \line??? nur an einer Stelle im \analysefile-Makro eine Dateizeile übergeben bekommt. Abschließend nennt man noch \telephone etwa in \title um und sorgt dafür, daß am Ende des Makros sowohl die Ausgabe, als auch gegebenenfalls das Löschen des Makros \title stattfindet. Ich bin sicher, durch finder.sty gestaltet sich das Briefschreiben unter LaTeX um einiges komfortabler. UNd mit etwas Phantasie steht der Einbindung in LaTeX-dokumente aller Art keine (fast) nichts im Wege. [Quelle: c't, magazin für computer technik, 3/92, Seite 214ff. Autor : Steffen Steinhäuser]