nroff ist ein Textformatierer, der -- falls ueberhaupt -- dann als Grundlage der Manpages bekannt ist. Wenn man als Entwickler heutzutage immer noch eine Manpage mit seinem Programm mitliefern will (was leider immer seltener wird), dann ist das zumeist der Zeitpunkt, an dem man zum ersten Mal nroff-Code sieht und erschrocken und unglaeubig lieber schnell das Weite suchen will. Lieber schaut man sich dann nach einem Programm um, das XML oder Markdown in Manpages uebersetzt, um sich bloss davor druecken zu koennen, dieses kryptische Durcheinander verstehen oder gar schreiben zu muessen.
Doch ohne nroff gaebe es Unix und damit GNU/Linux wohl nicht in der heutigen Form. Die historische Bedeutung dieses Programms ist gross ... und trotz des archaischen Stils besitzt es eine Schoenheit, die vor allem auf seiner Einfachheit bei gleichzeitiger Maechtigkeit basiert. Grund genug, einen Blick darauf zu werfen.
Historischer Hintergrund
Unix nahm seinen Anfang in Ueberlegungen Ken Thompsons zu einem neuen Dateisystem. Das MULTICS-Projekt scheiterte Mitte der 60er Jahre. Bell Labs zog sich daraus zurueck. Ken Thompson hatte daraufhin erstmal keine neue Aufgaben und liess seinen Dateisystemueberlegungen freien Lauf. Aus den Gespraechen und theoretischen Ueberlegungen wurde eine reale Umsetzung als fuer ihn, Dennis Ritchie und ein paar weitere Personen die Moeglichkeit bestand, eine nachts ungenutzte PDP-7 einer anderen Abteilung fuer ihre Experimente in Anspruch zu nehmen.
Das Projekt, das nun schon ein kleines Betriebssystem (in PDP-7-Assembler geschrieben) war, zeigte zunehmend sein Potenzial. Die nur in den Randzeiten nutzbare fremde PDP-7 wurde bald zur Beschraenkung. Ein eigener Computer musste her. Dieser konnte aber nur beschafft werden, wenn er einen Mehrwert fuer die Bell Labs schaffte -- und hier kommt nun nroff, bzw. sein Vorgaenger roff ins Spiel. Die Anschaffung der PDP-11 wurde naemlich dadurch durchgesetzt, dass man fuer die Patentabteilung eine Textverarbeitung zur Verfuegung stellte. Diese ist roff (spaeter nroff und troff), was sie damit zum ersten richtigen Anwenderprogramm von Unix macht.
Wenn die Mitarbeiter_innen (vor allem Sekreterinnen und Datentypistinnen) damals keine Probleme hatten, ihre Patentschriften mit ed fuer (n)roff zu schreiben, dann sollte uns erfahrenen Computernutzern von heute das sicherlich auch keine Probleme bereiten. Wir duerfen uns dafuer nur nicht selbst im Wege stehen, sondern muessen mit einem offenen Geist an die Sache gehen.
Technische Grundlagen
Nroff liest Eingabetext von Standard-In bzw. aus angegebenen Dateien, formatiert ihn um und gibt ihn wieder auf Standard-Out aus. Damit ist nroff zur Verwendung in Pipelines gedacht.
Nroff erzeugt reine Textausgaben, die im Terminal angezeigt werden koennen. Das Geschwisterprogramm troff erzeugt Ausgaben, die als PS oder PDF an grafischen Bildschirmen angezeigt oder auf Laserdruckern gedruckt werden koennen.
Die automatisch auf Debian installierte Implementierung von nroff aus dem groff Paket unterstuetzt leider kein UTF-8. Man muss daher die Eingangsdaten mit dem Programm `preconv' vorverarbeiten. (Aus diesem Grund verwende ich normalerweise die Implementierung der Heirloom Doctools, die besser fuer eine moderne Nutzung geeignet ist und UTF-8 voll unterstuetzt. Diese Implementierung kann aber nicht einfach als Debian-Paket installiert werden, daher sind alle Beispiele hier fuer die groff-Implementierung entworfen.)
Filling and Adjusting
Nroff hat einen einfachen Arbeitsmodus: Es liest Wort fuer Wort den Eingangstext ein und fuellt damit Zeile fuer Zeile (= Filling, also Auffuellen). Wenn eine Zeile so voll ist, dass das naechte Wort nicht mehr reinpasst, dann macht es einen Zeilenumbruch und erweitert die Wortzwischenraeume so lange bis die Zeile die gewuenschte Laenge erreicht hat (= Adjusting, also Ausrichten). So erzeugt nroff standardmaessig Blocksatz. Leerzeilen unterbrechen das Filling und beginnen einen neuen Absatz.
Beispiel:
Nehmen wir dieses Gedicht von Eichendorff als Ausgangstext:
Eine Blocksatzausgabe bekommen wir nun also mit:Weihnachten.
Markt und Straßen stehn verlassen,
Still erleuchtet jedes Haus,
Sinnend geh’ ich durch die Gassen,
Alles sieht so festlich aus.
An den Fenstern haben Frauen
Buntes Spielzeug fromm geschmückt,
Tausend Kindlein stehn und schauen,
Sind so wunderstill beglückt.
Und ich wandre aus den Mauern
Bis hinaus in’s freie Feld,
Hehres Glänzen, heil’ges Schauern!
Wie so weit und still die Welt!
Sterne hoch die Kreise schlingen,
Aus des Schneees Einsamkeit
Steigt’s wie wunderbares Singen –
O du gnadenreiche Zeit!
Code: Alles auswählen
:-Q preconv weihnachten | nroff
Weihnachten.
Markt und Straßen stehn verlassen, Still erleuchtet jedes Haus,
Sinnend geh’ ich durch die Gassen, Alles sieht so festlich aus.
An den Fenstern haben Frauen Buntes Spielzeug fromm geschmückt,
Tausend Kindlein stehn und schauen, Sind so wunderstill beglückt.
Und ich wandre aus den Mauern Bis hinaus in’s freie Feld, Hehres
Glänzen, heil’ges Schauern! Wie so weit und still die Welt!
Sterne hoch die Kreise schlingen, Aus des Schneees Einsamkeit
Steigt’s wie wunderbares Singen – O du gnadenreiche Zeit!
Nroff hat jeden Absatz gefuellt und beidseitig zu einem geraden Rand ausgerichtet. Als Absatz versteht es jeweils die durch Leerzeilen getrennten hintereinanderfolgenden Textzeilen.
Indem wir alle Leerzeilen entfernen, wird ein einziger Absatz daraus:
Code: Alles auswählen
:-Q grep . weihnachten | preconv | nroff
Weihnachten. Markt und Straßen stehn verlassen, Still erleuchtet
jedes Haus, Sinnend geh’ ich durch die Gassen, Alles sieht so
festlich aus. An den Fenstern haben Frauen Buntes Spielzeug
fromm geschmückt, Tausend Kindlein stehn und schauen, Sind so
wunderstill beglückt. Und ich wandre aus den Mauern Bis hinaus
in’s freie Feld, Hehres Glänzen, heil’ges Schauern! Wie so weit
und still die Welt! Sterne hoch die Kreise schlingen, Aus des
Schneees Einsamkeit Steigt’s wie wunderbares Singen – O du
gnadenreiche Zeit!
Befehle
Zeilen, die mit einem Punkt (oder Singlequote) beginnen, sind Befehlszeilen. So eine Zeile wird als nroff-Befehl interpretiert und stellt keinen Eingabetext dar.
Wir koennen die Zeilenlaenge veraendern, indem wir folgenden Befehl an den Anfang der Datei schreiben:
Code: Alles auswählen
.ll 40
Das Ergebnis ist dann:
Code: Alles auswählen
:-Q preconv weihnachten2 | nroff
Weihnachten.
Markt und Straßen stehn verlassen, Still
erleuchtet jedes Haus, Sinnend geh’ ich
durch die Gassen, Alles sieht so fes‐
tlich aus.
An den Fenstern haben Frauen Buntes
Spielzeug fromm geschmückt, Tausend
Kindlein stehn und schauen, Sind so wun‐
derstill beglückt.
Und ich wandre aus den Mauern Bis hinaus
in’s freie Feld, Hehres Glänzen,
heil’ges Schauern! Wie so weit und
still die Welt!
Sterne hoch die Kreise schlingen, Aus
des Schneees Einsamkeit Steigt’s wie
wunderbares Singen – O du gnadenreiche
Zeit!
Code: Alles auswählen
.pl 1n
Ebenso koennen wir das Filling an- und abschalten:
- .fi = fill (default)
- .nf = no fill
Oder das Adjusting aendern:
- .na = no adjusting
- .ad l = linksbuendig
- .ad r = rechtsbuendig
- .ad c = zentriert
- .ad b = beidseitig, also Blocksatz (default)
Diese Aenderungen greifen erst wenn ein neuer Absatz beginnt. D.h. wir brauchen eine Leerzeile im Eingabetext oder wir fuegen mit `.sp' (= space) explizit selbst eine ein oder wir brechen mit `.br' (= break) explizit selbst um.
Hier sind diese Moeglichkeiten beispielhaft verwendet:
Code: Alles auswählen
.pl 1n
.ll 60
.ad c
Weihnachten.
.sp
.nf
Markt und Straßen stehn verlassen,
Still erleuchtet jedes Haus,
Sinnend geh’ ich durch die Gassen,
Alles sieht so festlich aus.
.fi
.ad r
An den Fenstern haben Frauen
Buntes Spielzeug fromm geschmückt,
Tausend Kindlein stehn und schauen,
Sind so wunderstill beglückt.
.ad c
Und ich wandre
.br
aus den Mauern
Bis hinaus in’s freie Feld,
.br
Hehres Glänzen, heil’ges Schauern!
.br
Wie so weit und still die Welt!
.ll 30
.ad b
Sterne hoch die Kreise schlingen,
Aus des Schneees Einsamkeit
Steigt’s wie wunderbares Singen –
O du gnadenreiche Zeit!
Code: Alles auswählen
:-Q preconv weihnachten3 | nroff
Weihnachten.
Markt und Straßen stehn verlassen,
Still erleuchtet jedes Haus,
Sinnend geh’ ich durch die Gassen,
Alles sieht so festlich aus.
An den Fenstern haben Frauen Buntes Spielzeug fromm
geschmückt, Tausend Kindlein stehn und schauen, Sind so wun‐
derstill beglückt.
Und ich wandre
aus den Mauern Bis hinaus in’s freie Feld,
Hehres Glänzen, heil’ges Schauern!
Wie so weit und still die Welt!
Sterne hoch die Kreise schlin‐
gen, Aus des Schneees Ein‐
samkeit Steigt’s wie wunder‐
bares Singen – O du gnadenre‐
iche Zeit!
Gedichtformatierung
Ein Gedicht sollte natuerlich angemessen formatiert werden. D.h. die Zeilen sollen unveraendert bleiben, alles soll ein Stueck eingerueckt werden und wir wollen eine Zeilenzaehlung. Nroff bietet das natuerlich alles:
Code: Alles auswählen
.pl 1n \" Seitenlaenge auf 1 Zeile
.ll 60 \" Zeilenlaenge auf 60 Zeichen
.ad c \" zentrierter Text
Weihnachten.
.sp \" eine Leerzeile
.nm 1 3 2 8 \" Zeilennummern, beginnend mit 1,
.\" jede 3. nummerieren, 2 Zeichen Abstand
.\" zum Text, alles 8 Zeichen einruecken
.nf \" kein Filling (und folglich auch kein Adjusting)
Markt und Straßen stehn verlassen,
Still erleuchtet jedes Haus,
Sinnend geh’ ich durch die Gassen,
Alles sieht so festlich aus.
An den Fenstern haben Frauen
Buntes Spielzeug fromm geschmückt,
Tausend Kindlein stehn und schauen,
Sind so wunderstill beglückt.
Und ich wandre aus den Mauern
Bis hinaus in’s freie Feld,
Hehres Glänzen, heil’ges Schauern!
Wie so weit und still die Welt!
Sterne hoch die Kreise schlingen,
Aus des Schneees Einsamkeit
Steigt’s wie wunderbares Singen –
O du gnadenreiche Zeit!
Generell kann man mit einem Backslash Escape-Sequenzen einleiten, um beispielsweise innerhalb eines Wortes die Schrift zu wechseln oder um Variablen auszugeben oder um Sonderzeichen und bestimmten Leerraum einzufuegen. Das geht aber ueber diese Einfuehrung hinaus.
Das Ergebnis ist folgendes:
Code: Alles auswählen
:-Q preconv weihnachten4 | nroff
Weihnachten.
Markt und Straßen stehn verlassen,
Still erleuchtet jedes Haus,
3 Sinnend geh’ ich durch die Gassen,
Alles sieht so festlich aus.
An den Fenstern haben Frauen
6 Buntes Spielzeug fromm geschmückt,
Tausend Kindlein stehn und schauen,
Sind so wunderstill beglückt.
9 Und ich wandre aus den Mauern
Bis hinaus in’s freie Feld,
Hehres Glänzen, heil’ges Schauern!
12 Wie so weit und still die Welt!
Sterne hoch die Kreise schlingen,
Aus des Schneees Einsamkeit
15 Steigt’s wie wunderbares Singen –
O du gnadenreiche Zeit!
Weitere Features
Nroff kann noch weit mehr:
- Kopf- und Fusszeilen
- Fussnoten
- verschiedene Schriften
- mehrspaltigen Text
- Schusterjungenvermeidung
- Tabellen (mit dem Hilfsprogramm `tbl')
- Literaturverzeichnisse (mit `refer')
- Bedingungen, Variablen
- (roemische) Seitennummern, Kapitelnummern und beliebige sonstige Zaehler
- Macros
Die Details findet man in der Dokumentation, fuer groff, bzw. fuer Heirloom nroff/troff.
Macropakete
Mittels Macros wurden Macropakete geschrieben, die mit `-m' verwendet werden koennen.
Das wichtigste Macropaket ist `an', das mit dem Aufruf `nroff -man' fuer Manpages verwendet wird. Dies laesst sich schnell testen:
Code: Alles auswählen
:-Q zcat /usr/share/man/man1/nroff.1.gz | nroff -man
NROFF(1) NROFF(1)
NAME
nroff - emulate nroff command with groff
SYNOPSIS
nroff [-CchipStUvwW] [-dcs] [-Mdir] [-mname] [-nnum] [-olist] [-rcn]
[-Tname] [file ...]
nroff --help
nroff -v | --version
DESCRIPTION
The nroff script emulates the nroff command using groff. [...]
Wenn man sich (mit `zless') den Quellcode der Manpage anschaut, dann erkennt man manches wieder, was wir schon kennengelernt haben, wie Befehlszeilen, die mit Punkt beginnen, und Kommentare. Man findet nroff-Kommandos, die aus zwei Kleinbuchstaben bestehen, und Macrokommandos, die aus ein oder zwei Grossbuchstaben bestehen. Letztere werden im Macropaket (oder wie im Beispiel von `OP' in der Manpage selbst) mit `.de' definiert (`..' markiert das Ende der Definition.)
Kurz zum Verstaendnis: `.SH' ist ein Section Heading. `.PP' ist ein (eingerueckter) Paragraph. `.B' steht fuer Bold Font (also Fettschrift), `.BR' bedeutet, dass das erste Argument fett formatiert werden soll und das zweite im nomalen (Roman) Font. `.SY' und `.OP' sind zur Angabe von Befehlsnamen (System Command) und Operatoren/Argumenten ... was man in Manpages halt so braucht.
Dass in nroff alle Befehle und Namen nur ein oder zwei Buchstaben haben, ist der Zeit seiner Entstehung geschuldet. Das muss man so akzeptieren. (Groff-Erweiterungen haben teilweise laengere Namen.)
Ein weiteres wichtiges Macropaket ist MS, also eigentlich `s', das man mit `-ms' nutzt. Damit lassen sich vor allem technische Papers gut schreiben. Es eignet sich auch gut als Basis fuer eigene Macropakete.
Troff
Troff ist der grosse Bruder zu nroff. Im Gegensatz zu nroff, das auf die Ausgabe von reinem Text im Terminal beschraenkt ist, kann troff beliebige Ausgaben fuer Laserdrucker, Plotter und PDF erzeugen. Es hat folglich deutlich mehr Faehigkeiten.
Generell kann mit troff & Co. jede nroff-Datei auch in ein PDF formatiert werden, wie beispielsweise eine Manpage:
Code: Alles auswählen
zcat /usr/share/man/man1/nroff.1.gz | troff -man | grops | ps2pdf - nroff.pdf
Dazu gehoeren:
- verschiedene Schriftarten in verschiedenen Schriftgroessen
- Linien und sonstige grafische Darstellungen wie Diagramme (mittels `pic' und `grap')
- mathematische Formeln beliebiger Komplexitaet (mittels `eqn')
Letztlich ist mit troff so gut wie alles moeglich was mit Latex auch moeglich ist (wenn auch in etwas archaischerer Weise). Einige bekannte Buecher sind damit gesetzt worden, siehe: https://www.troff.org/pubs.html
Schluss
Ich selbst verwende nroff und troff schon lange und regelmaessig. Fuer kuerzere Texte nutze ich nroff mit ein paar angepassten Macros. Bewerbungen und laengere Texte bis hin zu meiner Masterarbeit habe ich mit troff gesetzt. Man darf dabei natuerlich keinen heutigen Komfort erwarten, aber das tut man bei einem alten Rennwagen ja auch nicht, trotzdem ist es ein tolles Gefuehl, damit zu fahren ... der Sound, die Strasse direkt zu spueren, die Hitze, der Geruch ... so aehnlich sind nroff und troff auch -- einfach etwas fuer Liebhaber! ... und zum Verstaendnis von Unix und seiner Geschichte unerlaesslich.
Viel Vergnuegen beim Rumspielen!