15.10.2015 / by
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.
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.
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.