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]