- Für Nutzer, die Webartikel direkt im Terminal lesen möchten, stellt James' Coffee Blog seine Blogbeiträge auch im Format von Linux-Handbuchseiten bereit
- Selbst bei derselben URL wird per HTTP Content Negotiation statt HTML ein roff-Dokument ausgeliefert, wenn der Client
Accept: text/roff sendet
- Die
.man-Datei jedes Beitrags wird aus einem Template mit den Abschnitten TITLE, AUTHOR, PUBLISHED, POST und URL erzeugt
- Im Haupttext wird der Markdown-Originaltext verwendet, damit er lesbarer ist als HTML; in Handbuchseiten sind die Abstände jedoch nicht immer sauber ausgerichtet
- NGINX erkennt Anfragen nach
text/roff und schreibt die URL auf eine .man-Datei um, sodass man sie mit curl speichern und anschließend etwa mit man ./post.page öffnen kann
Blogbeiträge mit man lesen
- Handbuchseiten unter Linux sind die Standardmethode, um die Nutzung von Befehlen im Terminal nachzuschlagen, und werden üblicherweise mit
man <command> geöffnet
- Zum Beispiel lässt sich die Handbuchseite des Befehls
tac so anzeigen
man tac
- James' Coffee Blog hat einen Ablauf eingerichtet, mit dem sich auch Web-Blogbeiträge auf dieselbe Weise lesen lassen: Von der Beitrags-URL wird eine
roff-Version heruntergeladen und mit man geöffnet
- Ein reales Anfragebeispiel sieht so aus
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page
Formatauswahl per HTTP Content Negotiation
- Kern der Implementierung ist HTTP Content Negotiation, bei der der Client dem Server das gewünschte Antwortformat mitteilt
- Der Header
Accept wird verwendet, um den gewünschten Content-Type zu übermitteln
- Zum Beispiel bedeutet
Accept: image/png, dass nach Möglichkeit eine PNG-Datei gesendet werden soll
- Man kann auch mehrere Content-Types und Prioritäten angeben; hier wird jedoch nur die Anforderung eines bestimmten Formats genutzt
- Wenn ein Blogbeitrag im Format einer Handbuchseite empfangen werden soll, sendet man den Header
Accept: text/roff
- Der Server erkennt diesen Header und gibt statt HTML eine text/roff-Antwort zurück, die sich mit
man öffnen lässt
Erzeugung der .man-Dateien
- Linux-Handbuchseiten werden in der roff-Syntax geschrieben
- Die Website wurde so angepasst, dass für jeden Blogbeitrag eine
man-Page-Version erzeugt wird
- Die verwendete Template-Struktur sieht wie folgt aus
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
- Das Template verwendet den Domainnamen als Header und erstellt fünf Abschnitte
- TITLE
- AUTHOR
- PUBLISHED
- POST
- URL
- Im Haupttext wird der Markdown-Originaltext verwendet
- In der Handbuchseite passen die Abstände nicht immer sauber
- Dennoch war er besser lesbar als HTML, und im Vergleich zu reinem Text gingen weniger Informationen über Überschriften und Absatzstruktur verloren
Mit curl abrufen und mit man öffnen
- Die
roff-Version eines Blogbeitrags kann mit folgendem Befehl angefordert werden
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
- Das gespeicherte Ergebnis lässt sich wie eine lokale Handbuchseite öffnen
man ./post.page
- Wenn ein normaler Browser dieselbe Beitrags-URL anfragt, erhält er die HTML-Version
- Der obige
curl-Befehl fordert dagegen für dieselbe URL ausdrücklich die text/roff-Version an
Umschreiben auf .man-Dateien in NGINX
- Der Server behandelt
text/roff-Anfragen separat mit wenigen Zeilen NGINX-Konfiguration
- In
/etc/nginx/nginx.conf wird eine Variable deklariert, die ein Flag setzt, wenn ein bestimmter Content-Type erkannt wird
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
- In der Site-Konfigurationsdatei unter
/etc/nginx/sites-enabled wird eine Regel hinzugefügt, die Anfragen nach roff-Seiten verarbeitet
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
- Diese Einstellung entfernt den abschließenden Slash der URL und hängt
.man an, wenn der Header Accept: text/roff vorhanden ist
- Dadurch liest NGINX statt der jeweiligen
index.html die entsprechende .man-Datei eines Beitrags
- So entsteht eine Konfiguration, mit der sich derselbe Blogbeitrag im Webbrowser als HTML und im Terminal als Linux-Handbuchseite lesen lässt
1 Kommentare
Hacker-News-Kommentare
Es wäre cool, ein deb-Repository als eine Art Blog-Abonnement anzubieten
So könnte man mit
apt updatealle Artikel abrufen und mitman your-blogden neuesten Beitrag sowie Links zum Gesamtindex aller Beiträge sehenIch glaube, ich hätte Angst, so etwas zu abonnieren
Diese lassen sich lokal mit dem Paket dwww ansehen: „Read all on-line documentation with a WWW browser“
https://packages.debian.org/bookworm/dwww
Joerg Jaspert war früher der Paketbetreuer der Linux Gazette: https://people.debian.org/~joerg/ (2002)
Das war eines der besten Beispiele, die ich bisher dafür gesehen habe, wie Informationsvermittlung und Dokumentation ins Betriebssystem integriert werden können, und es machte insbesondere Man-/Info-Dokumente nützlicher als traditionelle terminalbasierte Oberflächen
Es gibt auch Debian Planet als Debian-bezogenen Blog, aber soweit ich weiß, wurde es nie als offizielles Debian-Paket bereitgestellt
Ehrlich gesagt ist RSS für das Abonnieren von Blogs wahrscheinlich die bessere Wahl
Unter https://github.com/capjamesg/jamesg.blog.deb gibt es Inhalte, mit denen sich mit den folgenden Befehlen eine deb-Datei erzeugen lässt, die nur Manpages enthält
git clone [https://github.com/capjamesg/jamesg.blog.deb](<https://github.com/capjamesg/jamesg.blog.deb>)cd jamesg.blog.debdpkg-deb --build --root-owner-group jamesg.blogsudo dpkg -i jamesg.blog.debDanach sollte eine Ausgabe wie
Processing triggers for man-db (2.9.1-1) ...erscheinen; das bedeutet, dass die Manpage fürman jamesg.blogverfügbar istIm Moment ist es noch nur ein Platzhalter, aber ich werde es wahrscheinlich morgen fertigstellen
Vielleicht wird daraus bald ein Blogbeitrag
Man kann es auch direkt an
manweiterleiten, ohne zu forken oder temporäre Dateien zu verwendencurl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l -{curl,wget}in Befehle zu pipenEin Freund lässt einen Freund nicht einen Stream direkt in einen Befehl pipen
https://news.ycombinator.com/item?id=39554044
Nur zur Info:
curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l /dev/stdinfunktioniert in meiner UmgebungMan muss die roff-Datei also nicht lokal speichern
bashzu pipen, gilt im Allgemeinen als schlechte PraxisIch persönlich finde das in Ordnung. Wer die sicherheitsrelevanten Folgen versteht, kennt mit hoher Wahrscheinlichkeit auch diese Umwandlungsmethode, daher muss man sie nicht extra erwähnen
Für Anfänger ist das aber keine gute Empfehlung. Irgendwann kann einen das erwischen. Wenn die eigenen Fähigkeiten wachsen, lernt man solche Möglichkeiten ohnehin kennen, und hoffentlich bis dahin auch ihre Implikationen
Nicht von mir geschrieben: https://www.seancassidy.me/dont-pipe-to-your-shell.html
/usr/bin/man: illegal option -- lIch habe versucht, einen funktionierenden Einzeiler mit Pipe für den Mac zu bauen, bin aber immer wieder auf Fehler gestoßen
Die
man-Implementierung unter macOS hat kein Flag-l. Ich habe die Manpage geprüftman -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)Wenn es um URLs geht, die im Terminal etwas Unterhaltsames tun, fällt mir etwas ein, das ich früher auf textfiles.com gesehen habe
Es zeigt einen kurzen animierten Film mit VT100-Terminalcodes, alles aus einer einzigen URI
Auf modernen Systemen kann man eine Geschwindigkeitsbegrenzung setzen
curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>) && resetresetist dabei, weil das Terminal kaputtgehen kannAndere terminalbasierte URIs sind
curl cheat.sh/tar, das Nutzungsbeispiele für das Programm nach dem/holt, undcurl wttr.in/berlin, das Wetterinformationen mit Terminal-Formatierung abruftEigentlich ist es ziemlich simpel, und der schwierigste Teil ist die Erzeugung der Frames
Das geht mit
ffmpeg+img2txt.py: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...Es gibt einen alten Mirror von https://16colo.rs/, sodass man den Großteil der jemals veröffentlichten ANSI-Art sehen kann
Beispiel:
curl ansi.hrtk.in/ungenannt_1453.anshttps://itsfoss.com/star-wars-linux/
trittykann man 1200/9600 BPS Übertragungsgeschwindigkeit nachahmenJetzt fehlt nur noch ein Konverter von Markdown nach roff, aber wie sich herausstellt, gibt es den schon
https://github.com/postmodern/kramdown-man
https://rtomayko.github.io/ronn/ronn.1.html
https://kristaps.bsd.lv/lowdown/
[0]: https://pandoc.org/
md2groffgibt es in der suckless/2f30/cat-v-Community schon seit Langemhttps://codeberg.org/nereusx/md2roff
Es gibt ein Emacs-Paket, das SICP von Abelson und Sussman im Info-Verzeichnis installiert
Man muss nur
M-x package-install sicp RETeingebenAls ich das gesehen habe, dachte ich, dass man mit einem angepassten Feed-Reader vielleicht auch ein ganzes Bücherregal voller Blog-Archive installieren könnte
Wenn man Info in Emacs liest, kann man auch Lesezeichen verwenden
chicken-schemeinstallieren. Danach als root ausführenchicken-install srfi-203chicken-install srtfi216Die
~/.csircfür SICP sieht so aus(import scheme)(import (srfi 203))(import (srfi 216))(define (inc x) (+ x 1))(define (dec x) (- x 1))Danach kann man wie gewohnt user geiser und geiser für chicken verwenden
Ich könnte die Antwort vermutlich im Internet finden, aber ich wollte HN fragen
Ich erinnere mich, dass mir in der Highschool auf HP-UX jemand gezeigt hat, wie man mit irgendeiner Tastenkombination zu einem unterstrichenen Wort springt, also zu einem Abschnittsverweis, aber ich weiß absolut nicht mehr, welche Taste das war
Ich habe auch
man(1)undman(7)geprüft, aber nichts gefunden. Vielleicht ist es eine falsche Erinnerungman ohmanim Wesentlichennroff -man /usr/share/man/man1/ohman.1 | $PAGERistMan interagiert also nicht mit man oder nroff, sondern mit dem Pager
Heute ist
lessam verbreitetsten, undmoreist in der Praxis möglicherweise ebenfalls less, aber früher gab es andere, und HP-UX könnte etwas wiepgverwendet habenpggehörte zur AT&T-Welt,morezur BSD-Welt undlesszur GNU-WeltAlle drei starten mit
/eine RegExp-Suche, sodass man unabhängig von der Unterstreichung danach suchen kannlessunterstützt auch Tag-Dateien, sodass man mittzum nächsten Tag springen kanndthelpview. Der könnte man-Seiten angezeigt habeninfoöffnetIronischerweise wurde ein erheblicher Teil der ursprünglichen groff-Dokumentation in texinfo geschrieben: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
Ich weiß nicht, warum dieser kleine Punkt meinen inneren Erbsenzähler so getriggert hat. Vielleicht, weil im Internet jemand ein klein wenig falschlag.
Vielleicht auch, weil es von Anfang an unnötig Linux-zentriert war oder weil ich etwas anderes erwartet hatte und es am Ende nur eine kurze Demo von NGINX-Content Negotiation war.
Jedenfalls gibt es ein paar unnötige Dinge, die ich unbedingt sagen will.
Streng genommen wird kein roff zurückgegeben. Dinge wie
.THsind nicht roff selbst, sondern Teil eines Makropakets zum Schreiben von man-Seiten.Ich war enttäuscht, dass es keine Markdown-to-roff-Konvertierung gab. Ich dachte, das wäre der interessante Teil dieses Beitrags, und man hätte dafür wenigstens ein bestehendes Tool verwenden können.
Ähnlich ist deshalb auch die Textformatierung eigentlich nicht ganz korrekt. roff-Eingaben gehen absichtlich von einer Zeile pro Satz aus, um
.am Satzende von.mit anderer Bedeutung zu unterscheiden.Außerdem können alle Zeilen, die mit
.beginnen, als Befehle interpretiert werden und Probleme verursachen.Oder ich bin einfach nur ein grantiger alter Mann.
Andere Tools wie
groffundnroffhaben es noch verwirrender gemacht.Ein Beitrag, der nur erklärt, „was roff/man page/nroff/andere Varianten sind und wie man sie verwendet“, könnte für sich genommen schon ein guter Blogpost sein.
Eine kurze und klare Erklärung hätte ich auch gut gefunden, und sie wäre vermutlich auch für andere hilfreich.
Markdown-to-roff hatte ich für v2 vorgesehen. Als ich darüber nachzudenken begann, wie ich einen Parser implementieren könnte, hat mich jemand auf https://github.com/sunaku/md2man hingewiesen, und das scheint dieses Problem zu lösen.
Ich muss nur noch herausfinden, wie ich das in meine Python-Seite integriere, die auf GitHub Pages läuft, also braucht es noch etwas Feinschliff.
Pandoc kann Markdown sehr einfach in man-page-roff umwandeln.
Wenn man das in die gegebene Vorlage einsetzt, würde es viel mehr wie eine echte man-Seite aussehen.
Der korrekte Medientyp ist laut RFC 4263 text/troff: https://www.rfc-editor.org/rfc/rfc4263.html
Coole Idee. Jetzt muss man nur noch die Uhr starten, bis jemand auf „meine Blogposts als spielbares DOOM WAD bereitstellen“ kommt.