Markdown your life

Meine Liebe zu Markdown hat sich noch weiter entwickelt, sodass ich jetzt alle meine Vorlesungsmaterialen mit Markdown erstellen. Auch Notizen und andere Dokumente fertige ich in diesem Format an.

Vor längerer Zeit hatte ich darüber geschrieben, wie ich meine Vorlesungsfolien für Lehrveranstaltungen im Bereich Web-Technologien mit Markdown schreibe und dann zu HTML konvertiere. Dieser Ansatz hat sich auch gut bewährt. Allerdings passt er nicht so gut zu anderen Veranstaltungen, bei denen ich lieber PDF-Folien und vor allem auch ein Skript benötige.

Ausgehend von meiner damaligen Idee habe ich mir einen “Compiler” geschrieben, der aus einer einzigen Markdown-Quelle sowohl PDF-Folien und ein PDF-Skript als auch HTML-Folien mit Kommentaren erzeugen kann. Genaugenommen habe ich den Compiler drei Mal geschrieben:

  • Als schnellen, schmutzigen Hack in Java,
  • in einer sauber strukturierten Variante in Java, mit Objektmodell
  • und dann noch einmal in Ruby.

Die Ruby-Version ist deutlich kürzer als die Java-Variante und läuft sogar schneller. (Nicht weil Ruby schneller ausgeführt würde aber weil viele Markdown-Dateien im Spiel sind, die einzeln compiliert werden und die Java-VM startet nicht so schnell.) Der Compiler ist auf GitHub zu finden.

Der Compiler liest die Markdown-Verzeichnisse ein und erzeugt dann entweder direkt HTML-Dateien oder er generiert LaTeX-Sourcen, die dann über pdflatex in PDF-Dateien umgewandelt werden. Im letzteren Fall wird dann für die Folien die Klasse Beamer verwendet und für das Skript KOMA-Skript.

Verzeichnisstruktur

Eine Präsentation ist einfach nur eine Verzeichnisstruktur, in der sich Markdown-Dateien, Bilder und ein paar wenig Metadaten befinden. Damit die Ordnung erhalten bleibt, beginnen die Verzeichnis und Dateinamen mit Zahlen. Eine beispielhafte Struktur sähe so aus:

├── 01_auffrischung
│   ├── 01_typen.md
│   ├── 02_kontrollstrukturen.md
│   ├── img
│   │   ├── address-length.pdf
│   │   └── address.pdf
│   └── metadata.properties
├── 02_junit_javadoc
│   ├── 01_programmierstil.md
│   ├── 02_junit.md
│   ├── img
│   │   ├── begriffe.pdf
│   │   ├── javadoc-example.png
│   └── metadata.properties
├── Makefile
├── metadata.properties
└── presentation.mk

Die Datei metdata.properties im Hauptverzeichnis enthält Informationen zu der Präsentation, die von den entsprechenden Dateien in den Unterverzeichnissen noch angepasst werden können. Hier ein Beispiel:

title_1=Techniken der Programmentwicklung (TPE)
title_2=Vorlesung - Hochschule Mannheim
copyright=© 2015 Prof. Thomas Smits
default_language=Java
author=Prof. Thomas Smits
image_dir=img
description=Details zur Vorlesung.
term=Wintersemester 2015/2016

In den Unterverzeichnissen werden dann noch die Dateinamen für die Kapitel konfiguriert:

chapter_no=Kapitel 1
chapter_name=Auffrischung
resultfile=TPE_01_Auffrischung

Aufbau der Markdown-Dateien

Die einzelnen Markdown-Dateien enthalten ein oder mehrere Kapitel der Präsentation. Ich persönlich habe in jeder Datei immer nur ein Kapitel, der Compiler akzeptiert aber jede beliebige Anzahl. Ein Kapitel wird immer durch eine Markdown-Überschrift auf der obersten Ebene # eingeleitet. Die einzelnen Folien werden dann einfach durch eine Überschrift auf der zweiten Ebenen definiert ##.

# Typen und Operatoren

## Java Schlüsselworte

Java hat 50 __Schlüsselworte__ **(keywords)**

```console
abstract  continue  for         new        switch
assert    default   if          package    synchronized
boolean   do        goto        private    this
break     double    implements  protected  throw
byte      else      import      public     throws
case      enum      instanceof  return     transient
catch     extends   int         short      try
char      final     interface   static     void
class     finally   long        strictfp   volatile
const     float     native      super      while
```

---
Java Schlüsselworte dürfen nicht für __Bezeichner__ **(identifier)**,
d.h. Variablennamen, Klassennamen oder Methodennamen verwendet werden.

Das Schlüsselwort `goto` ist zwar reserviert, wird aber in der Sprache
gar nicht verwendet. Vermutlich hat man es zum Schlüsselwort gemacht, weil
in der Sprache C `goto` ebenfalls ein Schlüsselwort ist (mit dem man
unbedingte Sprünge machen kann) und man sich die Möglichkeit offen halten
wollte, später Sprünge in Java einführen zu können. Da `goto` aber zum so
genannten [Spaghetticode](http://de.wikipedia.org/wiki/Spaghetticode)
führt, ist es als positiv zu werten, dass Java solche Sprünge nicht unterstützt.

Im Rahmen dieser Vorlesung werden nahezu alle Schlüsselworte behandelt
werden. Die einzige Ausnahme stellen `strictfp`, `native` und `assert` dar.

  * __strictfp__ kennzeichnet Methoden und Klassen, bei denen
  Gleitkommaberechnungen strikt nach den Regeln von
  [IEEE745](http://de.wikipedia.org/wiki/IEEE_754) ablaufen müssen.
  * __native__ kennzeichnet Methoden, die nicht in Java, sondern direkt
  nativ für die Plattform, z.B. in C++, entwickelt wurden.
  * __assert__ erlaubt es, __Zusicherungen__ *(Assertions)* direkt im
  Quelltext anzugeben.

## Praxis-Tipp: Kommentare

  * Innerhalb von Methoden immer nur Zeilenkommentare verwenden
  * So können Methoden einfach durch einen Blockkommentar auskommentiert werden

```java
void methodeMitKommentaren() {
    // Erzeuge zwei Strings mit sinnvollem Inhalt
    String a = "Hallo";
    String b = "Welt";

    // Vertausche die Variablen
    swap(a, b);

    // Drucke Ergebnis aus
    System.out.println(a + " " + b);
}
```

---
Wenn Sie Eclipse verwenden, können Sie sehr komfortable Code aus- und
wieder einkommentieren, indem Sie einfach CTRL-SHIFT-C drücken.

Alles oberhalb der Trennlinie --- landet auf der Folie, alles unterhalb ist ein Kommentar, der nur im Skript zu sehen ist. Die Auszeichnungen _, __, * und ** werden unterschiedlich formatiert. Alles, was in __ eingeschlossen ist wird auch gleichzeitig in den Index des Skripts aufgenommen.

Die Folien zum Beispiel sehen dann wie folgt aus.

Folie Folie Folie

Außerdem wird noch ein Skript generiert, das die Folien und Kommentare enthält und eine ansprechende Titelseite, ein Inhaltsverzeichnis und einen Index vorweisen kann.

Folie

Durch die Verwendung von passenden LaTeX-Paketen bzw. JavaScript-Libraries bekommt man das Syntax-Highlighting für verschiedene Programmiersprachen geschenkt.

Funktionsweise des Compilers

Der oben bereits erwähnte Markdown-Compiler besteht aus einem Frontend, dass die Markdown-Dateien einliest und in ein Objektmodell verwandelt. Weiterhin gibt es ein Backend, das dieses Objektmodell in verschiedene Ausgabeformate umwandeln kann (zur Zeit LaTeX-Folien, LaTeX-Skript, HTML-Folien). Die verschiedenen Formate sind durch Renderer realisiert, die man austauschen kann.

Das Objektmodell hat als Wurzelknoten die Präsentation und dann Unterknoten für die einzelnen Folien. Eine Folie kann Text-, Listen-, Quelltext und andere Konten enthalten. Ein Listen-Knoten besteht dann wieder aus einzelnen Einträgen, die selbst wieder Textknoten sind usw.