2. Sphinx¶
Am Anfang (ca. 2002) war die Markup Sprache reStructuredText (reST). Das war
eine Idee aus der Welt der Programmiersprache Python, um Dokumentation zu
schreiben, die automatisch mit Hilfe von Umwandlungsprogrammen in
Ausgabeformate wie HTML und PDF umgewandelt werden kann. Die Programme sind im
Linux Paket docutils
enthalten, man installiert sie mit apt install
python3-docutils
(es ist immer Python3 zu bevorzugen, da Python 2 im Jahr
2020 eingestellt wurde). Wenn man eine Textdatei text.rst
mit
reStructuredText (Endung .rst
) geschrieben hat, dann wandelt man diese nach
HTML um mit dem Kommando:
rst2html text.rst text.html
Die Homepage der „docutils“ ist hier https://docutils.sourceforge.io/rst.html
Mit dem Text Quick reStructuredText kann man sich schnell einen Überblick über die wichtigsten Markup Befehle verschaffen:
Eine wichtige Eigenschaft von reST ist seine Erweiterbarkeit. Neue Markup-Befehle können einfach definiert werden.
Das Sphinx Projekt hat diese Erweiterbarkeit genutzt und reST zu einer kompletten Textverarbeitung weiterentwickelt, mit der man beliebige Dokumente erstellen kann.
Sphinx gibt es im Paket-Repository ihres Linux Rechners unter python3-sphinx
.
Man kann Sphinx auch vom Python Package Index installieren mit dem Kommando
pip install -U Sphinx
.
Um eine Dokumentationsprojekt zu beginnen, legt man ein neues
Unterverzeichnis an, z.B. dva-bericht
, und ruft darin das
Programm sphinx-quickstart
auf. Nach ein paar ja/nein Abfragen (siehe Log) wird dadurch das Gerüst einer neuen
Dokumentation generiert. Danach sind in dem Verzeichnis folgende Dateien:
dva-bericht/
conf.py <-- Konfiguration fuer Sphinx
index.rst <-- Die Hauptseite
make.bat <-- Zum Bauen der Doku unter Windows
Makefile <-- Zum Bauen der Doku unter Linux
_static <-- Hilfsverzeichnis, kann man ignorieren
_templates <-- Hilfsverzeichnis, kann man ignorieren
Mit sphinx-quickstart
kann man auch herausfinden, welche Version
von Sphinx man installiert hat, auf meinem Rechner erhalte ich folgende
Ausgabe (die Version kann bei Euch eine andere sein):
$ sphinx-quickstart --version
sphinx-quickstart 6.1.3
Die „richtige“ Dokumentation in einem bestimmten Format muss erst erzeugt
werden. Wenn man z.B. nach HTML ausgeben möchte, muss man eingeben:
make html
. Wenn man make
ohne Option eingibt, bekommt man eine
Liste aller Formate. Darunter sind html, latex, epub, man, texinfo,
text, xml und viele weitere. Die erzeugten HTML Dateien findet man
in _build/html
. Zum Betrachten ruft man einen Web-Browser
wie folgt auf:
firefox _build/html/index.html
Sollte das Dokument aus mehren Dateien bestehen, dann werden diese in
index.rst
inkludiert. Dieser Text besteht z.B. aus folgenden .rst
Dateien: index.rst
, schreibtipps.rst
, sphinx.rst
und
werkzeuge.rst
. Zum Inkludieren werden die drei Dateien ohne .rst
Endung in index.rst
aufgenommen:
.. toctree::
:maxdepth: 2
:numbered: <-- die Abschnitte werden nummeriert
intro <--- intro.rst
sphinx
schreibtipps
werkzeuge
anpassen
schluss
2.1. Überschriften¶
Die Überschriften kann man in verschiedenen Ebenen anlegen:
Ebene 1 <== Grosse Ueberschrift am Anfang in jeder .rst Datei
=======
Ebene 2
-------
Ebene 3
```````
Ebene 4
.......
2.1.1. Test Ebene 3¶
Die Nummerierung sollte 2.1.1 sein.
2.1.1.1. Test Ebene 4¶
Die Nummerierung sollte 2.1.1.1 sein. Mehr Ebenen braucht man nicht!
2.2. Querverweise¶
Man kann ganz einfach auf andere Abschnitte verweisen, wenn man vor dem Abschnitt mit:
.. _xyz:
ein „Label“ setzt. In diesem Fall hat das Label den Namen xyz
. Vor den
obigen Abschnitt „Überschriften“ habe ich das Label:
.. _ueberschriften:
gesetzt, somit kann ich nun auf diesen Abschnitt mit
:numref:`ueberschrift`
verweisen, der Link geht dann zu
Abschnitt 2.1.
Ein anderer Link: In Abschnitt 2.5 kann man nachlesen, wie man Formeln in
Sphinx schreibt. Das wurde gemacht durch :numref:`formeln`
.
2.3. Ein wenig Markup¶
In Sphinx wird der in reStructuredText definierte Markup verwendet, plus zusätzlicher Markup, der nur in Sphinx existiert. Hier sind ein paar Beispiele:
Wörter können in verschiedenen Schriftarten geschrieben werden:
fett, kursiv, Schreibmaschine
.
Immer gut zu gebrauchen sind Postenlisten oder Aufzählungslisten:
Mikroprozessoren
STM32L476
AVR Mega32U4
Spannungsregler
78L05
Widerstände
470 Ω
2,2 kΩ
Bei den Listen immer aufpassen, dass vor dem Beginn einer neuen Einrückung eine Leerzeile gemacht wird.
Eine Aufzählung:
Aufstehen
Zähne putzen
Frühstücken
Wie man in der .rst Datei sieht, kann man ab dem zweiten Punkt die Zahl
weglassen und stattdessen einfach #.
schreiben.
Sehr vielseitig zu verwenden sind auch Code-Blöcke. Das sind Abschnitte, die in „Computerschrift“ gesetzt werden. Ein Beispiel:
Zeile 1
Zeile 2
Zeile 3
In der .rst Datei habe ich dazu geschrieben:
.. code-block:: text
Zeile 1
Zeile 2
Zeile 3
Die Angabe hinter code-block::
bestimmt die Syntax, in der der
folgende Abschnitt hervorgehoben wird. Mit text
erfolgt keine
Hervorhebung. Andere Möglichkeiten sind hier z.B. c
, python
,
java
, bash
und so weiter.
Hier sind ein paar Beispiele:
/* c */
int main()
{
printf("Hello World\n");
return 0;
}
# python
L = []
for i in range(10):
L.append(i)
print(i)
# bash
if [ -f "/home/hhoegl/miniconda3/etc/profile.d/conda.sh" ]; then
. "/home/hhoegl/miniconda3/etc/profile.d/conda.sh"
CONDA_CHANGEPS1=false conda activate base
else
export PATH="/home/hhoegl/miniconda3/bin:$PATH"
fi
Kommentare schreibt man in die .rst Dateien wie folgt:
.. Das ist ein Kommentar. Es erfolgt
keine Ausgabe.
Alles weitere kann man der Sphinx Homepage ([SPHINX]) oder einem guten Tutorial entnehmen, z.B. [SPHTUT].
2.4. Programmtexte¶
Häufig müssen Sie Quelltextabschnitte in die Dokumentation aufnehmen. Sie können die Code-Blöcke entweder direkt in die .rst Datei aufnehmen oder aus einer Datei lesen:
Hier ist ein Beispiel für einen Codeabschnitt in Python. Man kann einen Codeabschnitt auch mit einer Über- bzw. Unterschrift versehen („caption“) und eine Referenz drauf setzen mit „numref“ (siehe Codeabschnitt 2.4.1):
# hallo.py
def hallo():
print("Hallo Welt")
hallo()
und hier ist ein Abschnitt in C. Die Zeilennummern werden durch :linenos:
aktiviert. Man kann auch den Beginn und die Schrittweite der Zeilennummern
einstellen.
1/* hallo.c */
2#include <stdio.h>
3
4int main()
5{
6 printf("Hallo Welt\n");
7 return(0);
8}
Wenn man den Quelltext aus einer Datei lesen möchte, dann geht das so (siehe
die Datei serial.c
):
.. literalinclude:: serial.c
:caption: C Code zum Ansprechen der seriellen Schnittstelle
:name: serialcode
:language: c
:linenos:
Hier ist die Ausgabe:
1#include <errno.h>
2#include <fcntl.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <termios.h>
7#include <unistd.h>
8
9int set_interface_attribs(int fd, int speed)
10{
11 struct termios tty;
12
13 if (tcgetattr(fd, &tty) < 0) {
14 printf("Error from tcgetattr: %s\n", strerror(errno));
15 return -1;
16 }
17
18 cfsetospeed(&tty, (speed_t)speed);
19 cfsetispeed(&tty, (speed_t)speed);
20
21 tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
22 tty.c_cflag &= ~CSIZE;
23 tty.c_cflag |= CS8; /* 8-bit characters */
24 tty.c_cflag &= ~PARENB; /* no parity bit */
25 tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
26 tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
27
28 /* setup for non-canonical mode */
29 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
30 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
31 tty.c_oflag &= ~OPOST;
32
33 /* fetch bytes as they become available */
34 tty.c_cc[VMIN] = 1;
35 tty.c_cc[VTIME] = 1;
36
37 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
38 printf("Error from tcsetattr: %s\n", strerror(errno));
39 return -1;
40 }
41 return 0;
42}
43
44void set_mincount(int fd, int mcount)
45{
46 struct termios tty;
47
48 if (tcgetattr(fd, &tty) < 0) {
49 printf("Error tcgetattr: %s\n", strerror(errno));
50 return;
51 }
52
53 tty.c_cc[VMIN] = mcount ? 1 : 0;
54 tty.c_cc[VTIME] = 5; /* half second timer */
55
56 if (tcsetattr(fd, TCSANOW, &tty) < 0)
57 printf("Error tcsetattr: %s\n", strerror(errno));
58}
59
60
61int main()
62{
63 char *portname = "/dev/ttyUSB0";
64 int fd;
65 int wlen;
66
67 fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
68 if (fd < 0) {
69 printf("Error opening %s: %s\n", portname, strerror(errno));
70 return -1;
71 }
72 /*baudrate 115200, 8 bits, no parity, 1 stop bit */
73 set_interface_attribs(fd, B115200);
74 //set_mincount(fd, 0); /* set to pure timed read */
75
76 /* simple output */
77 wlen = write(fd, "Hello!\n", 7);
78 if (wlen != 7) {
79 printf("Error from write: %d, %d\n", wlen, errno);
80 }
81 tcdrain(fd); /* delay for output */
82
83
84 /* simple noncanonical input */
85 do {
86 unsigned char buf[80];
87 int rdlen;
88
89 rdlen = read(fd, buf, sizeof(buf) - 1);
90 if (rdlen > 0) {
91#ifdef DISPLAY_STRING
92 buf[rdlen] = 0;
93 printf("Read %d: \"%s\"\n", rdlen, buf);
94#else /* display hex */
95 unsigned char *p;
96 printf("Read %d:", rdlen);
97 for (p = buf; rdlen-- > 0; p++)
98 printf(" 0x%x", *p);
99 printf("\n");
100#endif
101 } else if (rdlen < 0) {
102 printf("Error from read: %d: %s\n", rdlen, strerror(errno));
103 }
104 /* repeat read to get full message */
105 } while (1);
106}
Auch bei literalcode
kann man eine Bildüberschrift setzen und eine Referenz
angeben mit numref
(siehe Codeabschnitt 2.4.2).
Nun noch ein Beispiel, das zeigt, wie Sie einen Link auf eine Quelltextdatei
setzen. Im Verzeichnis sphinxbericht
gibt es die Datei hello_world.py
.
Es funktioniert nicht, wenn man die Datei im aktuellen Verzeichnis verlinkt:
hello_world.py (Link existiert nicht)
Der Grund ist, dass die Quelltextdatei nicht in den Ausgabeordner _build/html
kopiert wird.
Die Datei sollte in den Ordner _static
kopiert werden, dieser Ordner wird
komplett in das Ausgabeverzeichnis kopiert.
_static/hello_world.py (Link existiert)
2.5. Formeln schreiben¶
Formeln schreiben ist in Sphinx einfach: Man verwendet die gleiche Syntax wie in Latex!
Beispiel (Pythagoras): \(a^2 + b^2 = c^2\).
Die folgende Formel
wird so geschrieben:
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
Damit man math
verwenden kann, muss man die Sphinx Erweiterung
sphinx.ext.mathjax
in die Variable extensions
in conf.py
aufnehmen.
2.6. Literatur¶
Die Sphinx Homepage (besucht am 13.3.2023): https://www.sphinx-doc.org
Thomas Cokelaer, Sphinx and RST syntax guide, 2014 (besucht am 13.3.2023) https://thomas-cokelaer.info/tutorials/sphinx/rest_syntax.html