Am Anfang war Perl
Die Anfaenge waren grau und in einem Urschleim aus Regexes zu finden. Die Grundidee war, dass jede Ausgabedatei eine Eingabedatei hat, die prinzipiell bereits das ganze Dokument ist, gespickt mit speziellen Kommentaren, die im Anschluss durch das Skript expandiert werden -- z.B. in ein Inhaltsverzeichnis. Das weckte das Beduerfnis danach, irgendwo zentrale Daten zu haben, um sie nicht erst zusammensammeln zu muessen. Das Grundkonzept sah also wie folgt aus:
im Verz. in/ index abstracts im Verz. out/
+----------------+ | | +-------------+
| file1.html | \ / | file1.html |
| ... | ----> [perlscript] --------> | ... |
| fileN.html | \ | fileN.html |
+----------------+ \ +-------------+
\
`---> file.rss
Die Prozedur, um einen neuen Artikel einzufuegen sah also ungefaehr wie folgt aus:
fileN+1.htmlim Verzeichnisin/anlegen. Dort hinein den eigentlichen Artikel schreiben.- In der Datei
indexeinen Entrag mit dem Dateinamen, der Ueberschrift, dem Veroeffentlichungsdatum und der Position im Inhaltsverzeichnis anlegen - In der Datei
abstractseinen Eintrag mit dem Dateinamen, der Ueberschrift und dem Abstract erstellen. - Compilerlauf durchfuehren
Hinzu kam noch ein Problem -- die Wartarkeit. Ich moechte hier ausdruecklich nicht die Schuld auf Perl schieben, aber mein Compilerskript bestand aus zu vielen zu globalen Variablen, zuwenigen Prozeduren, zuvielen Regexes und absolut zuwenigen Kommentaren. Ich haette den neuen Compiler gerne basierend auf dem Alten in Perl geschrieben, aber dem stand entgegen, dass ich dazu den etwa ein Jahr alten Code ersteinmal wieder haette verstehen muessen. So blieb es dabei, bis mich irgendwann dann doch der Ehrgeiz packte, das Ganze nochmal neu anzugehen.
Sprachwahl
Die Sprache fuer die neue Implementation sollte C++ werden. Warum nicht wieder Perl? Ich fuerchte, weil ich Perl einfach nicht beherrsche. Die Sprache ist mir zu reich an Syntax. Einmal versehentlich etwas auf die Tastatur fallengelassen und schon hat man einen Laufzeitfehler ;)
Ok, ernsthaft: Mit C arbeite ich schon laenger und bin dabei meist ganz gut zurechtgekommen. Ich habe die Vorteile von C schaetzengelernt: Plattformunabhaengigkeit, indem jede Plattform einen eigenen Satz von Runtime-Bibliotheken mitbringt, wobei diese im Gegensatz zu einer Java-Runtime nicht auf jedem Zielsystem vorhanden sein muessen sondern nur auf einem Build-System. C ist relativ schnell, je nach Programm und zu guter Letzt kann man in C sehr schoene Dinge mit Pointern machen. Sicherlich, das was ich hier als Vorteile aufzaehle werden Viele als Nachteil ansehen. Ich aber nicht. Soweit C. Und C++ kann prinzipiell das Gleiche, ist dabei aber objektorientiert. Ich wollte es mal versucht haben. Diesem eher paedagogischen Gedankengang entspringt auch die Tatsache, dass ich die grundlegenden Verwendeten abstrakten Datentypen (Baum, Liste) selbst implementiert und nicht etwa die aus der C++-Runtime genutzt habe.
Es war ein Sprung ins kalte Wasser und entsprechend grausam sahen die ersten hundert Zeilen Code zum Teil auch aus.
Angestrebte Situation
Konzeptuell
Mit meinem neuen Compiler sieht die Sache bezueglich der Eingabe/Ausgabedateien und des Flusses zum Einfuegen eines Artikels nun so aus:
im Verz. in/ configfile im Verz. out/
+----------------+ | +-------------+
| file1.html | | | file1.html |
| ... | ----> [perlscript] --------> | ... |
| fileN.html | | \ | fileN.html |
+----------------+ | \ +-------------+
template \
`---> file.rss
Die Ausgabe ist also die Gleiche geblieben, einzig das Prozedere um sie zu erreichen hat sich stark vereinfacht:
fileN+1.htmlim Verzeichnisin/anlegen. Dort hinein den eigentlichen Artikel nebst allen Metadaten schreiben.- Compilerlauf durchfuehren
Die Artikeldateien
[article]
title=Homepage-Compiler
subtitle=oder: Wie ich mit C++ angefangen habe
author=ad001
date=09.07.2008
sortkey=20080709
path=ad001\Programmierung und Systemnahes\Programmierung
psepchar=\
showsubsites=0
showtoc=1
[abstract]
Mein erster Kontakt zu C++ war ein vorsichtiges Benutzen von Microsoft Visual C++, gefolgt von langem Meiden
von C++ -- bis ich ungefaehr vor einem Monat auf die Idee kam, mich mal wieder mit dieser Sprache (da ich
mittlerweile Unix-Benutzer bin natuerlich nicht mehr mit MS VS (falls die ueberhaupt noch C++ unterstuetzen
und sich nicht mittlerweile voellig auf C# und Visual Basic spezialisiert haben) sondern mit cc
und Makefiles -- wie sich das gehoert.
Hier findet der neugierige Leser also zum einen einen Bericht meiner Erfahrungen mit C++, gcc und (Free|Net)BSD
und zum anderen das Konzept hinter dieser Seite -- kein php, kein serverseitiges Skripting, nur HTML.
[body]
hier kommt dann der voll HTML-formatierte Artikelinhalt.
In meinen Augen irgendwo elegant. Ich muss allerdings zugeben, dass das Format ein paar Haken hat, was aber am Parsing liegt. Denn wenn man das ganze theoretisch betrachtet, so handelt es sich um eine kontextsensitive Sprache, welche hier zum Aufbau des Artikels genutzt wird. Zu erkennen z.B. daran, dass die Zeile title=Homepage-Compiler unterschiedliche Bedeutung bekommt, je nachdem, ob sie in der Section [article] oder [body] auftaucht. Schlimmer noch, das Auftauchen von [body] innerhalb von [article] wuerde den Rest der Datei zum Artikelinhalt machen. Andererseits sind diese Regeln so einfach verstaendlich, dass ich darauf verzichte, ein komplexeres Format zu erschaffen, nur weil es eindeutiger sein koennte...Zur Erklaerung der einzelnen Eintraege:
- title, subtitle, author und date duerften intuitiv klar sein.
- der sortkey ist eine Integerzahl, nach welcher die Artikel fuer die Liste der neuesten/letzten Artikel und den RSS-Feed sortiert werden. Je nach Lust und Belieben kann man sich hier fortlaufende Zahlen nehmen oder so wie ich das Datum als solche missbrauchen.
- der path gibt an, wo im Artikelbaum (der Compiler versucht grundsaetzlich, die Artikel hierarchisch zu sortieren, dies hat sich bisher als sinnvoll erwiesen) der Artikel einsortiert werden soll.
- Der Pfad-Trenner kann fuer jeden Pfad anders definiert werden, falls der Nutzer Lust dazu haben sollte. Das verschiebt Escaping-Probleme aus dem Compiler zum Nutzer hin.
- Es folgen noch zwei Flags zu Verzeichnissen, die ausgegeben werden koennen (so im Template vorgesehen): Ausgabe des Teilbaumes, der unter dem aktuellen Artikel liegt oder Ausgabe der Liste der Kapitelueberschriften in diesem Artikel
- Anschliessend folgen noch der Abstract und der eigentliche Artikelinhalt.
Das Template
Nachdem der Inhalt der Artikel sicher in den einzelnen Dateien verwahrt ist, kann man sich der Praesentation zuwenden. Die soll fuer alle Artikel prinzipiell gleich aussehen -- das schreit geradezu nach einem Template, in dem einzelne Tags dynamisch je nach Artikel durch Inhalt ersetzt werden. Damit ergibt sich in meinem Fall fuer das Template eine simple Implementation: Das Template ist die komplett formatierte Seite mit Platzhaltern an den entsprechenden Stellen. Um in medias res zu gehen, das Template zu dieser Seite sieht momentan wie folgt aus:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title><!--[filetitle]--></title>
<link rel="stylesheet" href="ad001.css" type="text/css" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="<!--[rssfilename]-->" />
</head>
<body>
<div id="head">
<p><!--[homelink]-->
Artikel vom: <i><!--[articledate]--></i>, last compiled on <!--[compiledate]--></p>
<h1><!--[articletitle]--></h1>
<h2><!--[articlesubtitle]--></h2>
</div>
<div id="abstract">
<p><!--[abstract]--></p>
</div>
<div id="sections">
<!--List of Sections:-->
<!--[sectionslist]-->
</div>
<div id="subpages">
<!--List of Subpages:-->
<!--[subpageslist]-->
</div>
<div id="content">
<!--[body]-->
</div>
</body>
</html>
Nun ja, ziemlich schlicht, aber das ist auch mein Stil hier :)Wenn ich mal ein wenig Zeit finde, kann ich auch das ja mal ein bisschen komplexer gestalten.
Der Compiler selbst
Wenn der Compiler gestartet wird, dann soll er was tun. Das, was er tut, laesst sich kurz wie folgt zusammenfassen:
- Konfiguration einlesen
- Nach Artikeldateien suchen
- Artikeldateien laden, Metadaten extrahieren
- Dirket zu kopierende Dateien (Graphiken, ...) kopieren
- Sortierte Liste der Artikel bilden, sortierten Artikelbaum bilden
- Template laden
- Template mit den bereits verfuegbaren und sich nicht nach Artikeln aendernden Daten ausfuellen
- Fuer jede Artikeldatei
- Bilde die Liste der Sektionen
- Bilde den Baum untergeordneter Artikel
- Uebergebe diesen Artikel dem Template, werte saemtliche Platzhalter aus, erzeuge die Ausgabedatei
- Erzeuge eine RSS-Datei
Warum so kompliziert?
Eine Frage mag beim Leser haengengeblieben sein -- warum so kompliziert? Warum nicht einfach ein Drupal, ein Wordpress, ein Postgres oder MySQL und gut?
Tjaa... irgendwie gefaellt mir an meiner Loesung, dass ich immer bei diskreten Dateien bleibe. Diese Dateien kann ich in einem Subversion-Repository halten oder per scp oder ftp durch die Welt schicken. Meine Homepage ist nur ein Haufen HTML-Dateien, sie funktioniert auf jedem Server. Ich habe keine Datenbank, die bei einem Update den Geist aufgeben kann und fuer die ich irgendwo einen Nutzernamen und ein Passwort brauche. Kein Crosssidescripting der Welt kann mir was anhaben. Und zu guter Letzt: Ich kann meine Homepage offline in einem Editor meiner Wahl bearbeiten. Ohne Klickibuntiwebbrowser drumrum. Einfach so.
Weil es mir Spass macht.