Documenting with Sphinx#
This page is dedicated to help editors to write RST files in XLiFE++ documentation.
Short introduction to Sphinx#
Sphinx is a python documentation generator, originally dedicated to python codes, but now accepting C/C++/Fortran codes. In comparison with Doxygen, Sphinx provides modern themes and the ability to write static pages very easily. Documentation can be generated in different formats: HTML, PDF (through LaTeX), EPUB, … The input files are written in RST format (or in Markdown format, with the dedicated extension).
Here is the Sphinx reference documentation
Configuration file and extensions#
When generating a documentation project, the most important file is the configuration file conf.py
in the source
directory. In this file, you will:
Include Sphinx extensions to enable additional RST directives and roles (aka commands);
Define configuration parameters of your website: global parameters, extensions parameters, …
Define the HTML theme (here we chose PyData)
Implement a
setup()
method to run python code before generating your documentation
When ready, you just have to call make
with the appropriate target to generate your documentation
Let’s talk now about the RST syntax.
The RST syntax#
RST files are ASCII formatted files with markups. Block markups are called directives and inline markups are called roles. Here is the general syntax of a directive and a role:
.. directive-name:: [directive-parameter]
directive-content
:role-name:`role-content`
Some directives need a parameter and others not. As in python syntax, the content is indented. Directive can also have options:
.. directive-name:: [directive-parameter]
:direction-option1: val1
:direction-option2: val2
directive-content
About paths#
For some directives or roles, you will have to give a filename with its path (images, code files, …). You may preferentially set absolute paths, but you just have to know one thing: in absolute paths, the first /
means the root directory of the project, namely the directory that contains conf.py
, i.e. source
directory in your Sphinx project.
Headings and tables of contents#
There is no special markup to define headings. Rather than imposing a fixed number and order of section title adornment styles, the order enforced will be the order as encountered. The first style encountered will be an outermost title (like HTML H1), the second style will be a subtitle, the third will be a subsubtitle, and so on. Here are the recommended characters: = - ` : . ‘ “ ~ ^ _ * + # and the adopted convention:
parts
#####
chapters
********
sections
++++++++
subsections
===========
subsubsections
--------------
paragraphs
..........
The toctree
directive is used to define tables of contents. Here is the one defined in index.rst
:
.. toctree::
:maxdepth: 2
:hidden:
:caption: Contents:
intro
examples
doc
language
api
events/index
The caption
option defines the title of the table of contents.
The maxdepth
option defines the number of levels used in the table of contents.
The hidden
option prevents the table of contents from being displayed in the left sidebar.
Then you give the file names you want to appear in the table of contents. You may have noticed there is no level information about the included files. So, how to define sublevels ? By using toctree
directive in child files.
With PyData theme, the toctree
defined in the root RST file (generally called index.rst
) defines the header menu.
Text styles#
The standard RST inline markup is quite simple: use
Use one asterisk for emphasis (italics). For instance: *text*.
Use two asterisks for strong emphasis (boldface): For instance: **text**.
Use double backquotes for code samples. For instance, ``text``.
Lists#
Unnumbered lists items start with a single markup such as - and the content of an item has to be indented properly if on several lines.
* This is a bulleted list with asterisk.
* It has two items, the second
item uses two lines.
- This is a bulleted list with dash.
- It has two items, the second
item uses two lines.
This is a bulleted list with asterisk.
It has two items, the second item uses two lines.
This is a bulleted list with dash.
It has two items, the second item uses two lines.
Numbered lists items start with a single markup such as a number followed by .
, or #.
and the content of an item has to be indented properly if on several lines. With #.
markup, numbering is automatical.
1. This is a numbered list.
2. It has two items too.
#. This is a numbered list.
#. It has two items too.
This is a numbered list.
It has two items too.
This is a numbered list.
It has two items too.
Description lists are very light syntax.
item 1
item 1 description
item 2
item 2 description
Images and figures#
The image
directive is used to display an image.
.. image:: /_static/events/roscoff18/affiche.png
:width: 80%
:align: center
The figure
directive is used to display an image with a caption (and a legend).
.. figure:: /_static/pictures/doc/bin_win_conf_1.png
:width: 80%
optional caption on a single line
optional legend
as a paragraph
Both have several options: width
, height
, align
, alt
, target
, …
target
is to set a link.
XLiFE++ loads the sphinx_subfigure
(sphinx-subfigure documentation) extension that provides subfigure
directive to create figures with several images.
.. subfigure:: AB
.. image:: /_static/pictures/examples/U_OmegaFig1.png
.. image:: /_static/pictures/examples/U_OmegaFig2.png
The subfigure
parameter is the definition the structure of the subfigure. A
represents the first image, B
the second one …
AB
means that there will be two figures side by side taking half the width, whereas A|B
means that the first image will be above the other one.
Tables#
Grid tables are described with a visual grid made up of the characters “-”, “=”, “|”, and “+”. The hyphen (“-”) is used for horizontal lines (row separators). The equals sign (“=”) may be used to separate optional header rows from the table body. The vertical bar (“|”) is used for vertical lines (column separators). The plus sign (“+”) is used for intersections of horizontal and vertical lines.
Caution
How tables are displayed in HTML documentation depends on the HTML theme. With PyData, column separators are not displayed.
+------------------------+------------+----------+----------+
| Header row, column 1 | Header 2 | Header 3 | Header 4 |
| (header rows optional) | | | |
+========================+============+==========+==========+
| body row 1, column 1 | column 2 | column 3 | column 4 |
+------------------------+------------+----------+----------+
| body row 2 | Cells may span columns. |
+------------------------+------------+---------------------+
| body row 3 | Cells may | - Table cells |
+------------------------+ span rows. | - contain |
| body row 4 | | - body elements. |
+------------------------+------------+---------------------+
Header row, column 1 (header rows optional) |
Header 2 |
Header 3 |
Header 4 |
---|---|---|---|
body row 1, column 1 |
column 2 |
column 3 |
column 4 |
body row 2 |
Cells may span columns. |
||
body row 3 |
Cells may span rows. |
|
|
body row 4 |
There is another useful way to define a table, by using list-table
directive. The main differences with grid tables are:
a list table can have a caption
a list table can’t have row/columns spanned cells
in a list table, you do not have to “draw” borders
in a list table, you can define several header rows or “header columns” (called stub columns)
in a list table, you define the width of each column (by a percentage)
row 1, column 1 |
row 1, column 2 |
row 1, column 3 |
row 1, column 4 |
---|---|---|---|
row 2, column 1 |
row 2, column 2 |
row 2, column 3 |
row 2, column 4 |
row 3, column 1 |
row 3, column 2 |
row 3, column 3 |
row 3, column 4 |
row 4, column 1 |
row 4, column 3 |
.. list-table:: the optional caption
:widths: 35 30 25 10
:header-rows: 1
:stub-columns: 1
* - row 1, column 1
- row 1, column 2
- row 1, column 3
- row 1, column 4
* - row 2, column 1
- row 2, column 2
- row 2, column 3
- row 2, column 4
* - row 3, column 1
- row 3, column 2
- row 3, column 3
- row 3, column 4
* - row 4, column 1
-
- row 4, column 3
-
Code blocks#
The code
directive is to be used to construct literal block. If the code language is specified (as a directive parameter), the content is parsed by the Pygments syntax highlighter and tokens are stored in nested inline elements with class arguments according to their syntactic category. The actual highlighting requires a style-sheet (e.g. one generated by Pygments, see the sandbox/stylesheets for examples). XLiFE++ provides its own style-sheet called XLiFE++
. This is the default style-sheet of code
directive.
If you want to include a code file, you will use literalinclude
directive instead and the language by its language
option.
The sphinx_copybutton
extension provides a small button in the top right corner of code
directive to copy content properly.
Now, if you want to display code listing in inline mode, you should use the xlifepp
specific role to display code with color highlighting, or the var
to display variable for instance to explain what they are.
When you want to refer to a XLiFE++ sub-library (for instance utils), you should use the lib
specific role.
Substitutions#
Substitutions are pieces of text and/or markup referred to in the text by |name|.
.. |xlifepp| replace:: **XLiFE++**
Every substitution is defined in /include/macros.txt
in order to be automatically included in every RST file, as it is configured in conf.py
.
Links and references#
Use \`Link text <url>\`\_
for inline web links. If the link text should be the web address, you don’t need special markup at all, the parser finds links in ordinary text.
You can also separate the link and the target definition like this:
`Link text`_
.. _Link text: url
Every target definition is written in /include/links.txt
in order to be automatically included in every RST file.
For email addresses, you will use the email
directive that obfuscates email address. This directive is defined in the sphinxcontrib.email
extension.
The ref
role is devoted to define a hyperlink to somewhere else in the Sphinx project identified by a hypertarget.
.. _hypertarget:
content
:ref:`hypertarget`
The doc
role is devoted to reference other documents of the project (aka other pages). You juste have to give as parameter the file without extension.
Referencing XLiFE++ C++ elements can be done with several roles: cpp:class
for classes, cpp:func
for functions, cpp:enum
for enumerations, cpp:struct
for structs, …
To reference a namespace, you will use cpp:any
.
Important
If you give the full name of a class or a function (with namespaces), it will define a cross-reference to the API documentation automatically. Adn then, you will add a ~ at the beginning, so that the text carrying the link will be only the class/function/… name.
:cpp:class:`xlifepp::Segment` // cross reference with text xlifepp::Segment
:cpp:class:`~xlifepp::Segment` // cross reference with text Segment
:cpp:class:`~xlifepp::subdivision::CartesianFig` // cross reference with text CartesianFig
:cpp:class:`~xlifepp::ClusterNode\<T>` // cross reference with text ClusterNode<T>
The sphinxcontrib.moderncmakedomain
(Sphinx Moderncmakedomain documentation) extension provides for instance the cmake:variable
role used for instance in Installation
Footnotes#
To define a footnote, you have to define a label between brackets and starting with #, followed by an underscore. Here is a sample taken from Installation:
As mentioned in the banner, a |cpp| compiler, `Cmake`_ and `Gmsh`_ have to be installed on your computer and defined in the |win| PATH [#winpath]_ system environnement variable. An EDI such as `CodeBlocks`_ and `Paraview`_ are not mandatory but highly recommended. Click on the *Configure* button.
Then, you have to write the footnote content. Here is the corresponding content of the previous footnote label:
.. [#winpath] A simple tool to edit the window path is `Windows Path Editor`_ if you have a version of |win| less or equal to 8, as PATH environment variable is shown in |win| preference pane as a single string. For recent |win| OS, this was improved and now there is one line for each directory in the PATH.
Admonitions#
Sphinx (and PyData theme) provides admonition directives: attention
, caution
, danger
, error
, hint
, important
, note
, seealso
, tip
, todo
, warning
, versionadded
, versionchanged
and deprecated
.
.. caution::
How tables are displayed in HTML documentation depends on the HTML theme. With `PyData`_, column separators are not displayed.
Those directives are special cases of the generic one: admonition
. In XLiFE++ projects, 3 custom admonitions are defined, one for each OS:
.. admonition:: |unix|
:class: unix
admonition-content
.. admonition:: |macOS|
:class: macos
admonition-content
.. admonition:: |win|
:class: win
admonition-content
To define the appearance of a custom admonition, you have to set some CSS, in the dedicated CSS file /_static/css/admonitions.css
. Here is CSS code concerning the Windows admonition:
:root {
--icon--win: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 34" width="28" height="24"><path fill="none" d="M0 0H24V24H0z"/><path d="M3 5.479l7.377-1.016v7.127H3V5.48zm0 13.042l7.377 1.017v-7.04H3v6.023zm8.188 1.125L21 21v-8.502h-9.812v7.148zm0-15.292v7.236H21V3l-9.812 1.354z"/></svg>');
}
.admonition.win {
border-color: rgb(155, 155, 155);
}
.admonition.win > .admonition-title {
background-color: rgba(155, 155, 155, 0.1);
border-color: rgb(155, 155, 155);
}
.admonition.win > .admonition-title::after {
background-color: rgb(155, 155, 155);
content:"";
-webkit-mask-image: var(--icon--win);
mask-image: var(--icon--win);
}
Advanced elements with sphinx_design extension#
Here is the Sphinx Design reference documentation. Here comes a little summary.
Grids#
Grids are based on a 12 columns system, which can be adapted to the size of the viewing screen.
The grid
directive can take one or four integers as parameter to set the number of columns according to the size of the viewing screen. The first integer is for extra-small viewing screens (<576px), the second one for small viewing screens (768px), the third one for medium viewing screens (992px) and the last one for large viewing screens (>1200px). If only a single integer is done, it is for all screens whatever their size.
The child grid-item
directive is sued to define each item of the grid. You can override the number of columns a single item takes up by using the columns
option of the grid-item
directive. As the total columns are 12, this means 12
would indicate a single item takes up the entire grid row, or 6
half. Alternatively, use auto
to automatically decide how many columns to use based on the item content. Like for grid columns, you can either provide a single number or four according to the size of the viewing screens.
.. grid:: 2
.. grid-item-card::
:columns: auto
A
.. grid-item-card::
:columns: 12 6 6 6
B
.. grid-item-card::
:columns: 12
C
A
B
C
Cards#
Cards contain content and actions about a single subject. A card is a flexible and extensible content container, it can be formatted with components including headers and footers, titles and images.
The card
directive needs to give a title and a content:
.. card:: Card Title
Card content
Card content
You can set images in a card through img-background
, img-top
, and img-bottom
options to card
.
Attention
If you want to add cards in grid items, you may use grid-item-card
directive, which combines grid-item
and card
Tabs#
The tab-set
directive defines a set of tabs. Each tab will be defined with the tab-item
directive:
.. tab-set::
.. tab-item:: Label1
Content 1
.. tab-item:: Label2
Content 2
Content 1
Content 2
Managing API with breathe extension#
This extension provides management of API documentation from XML files generated by Doxygen. It also provides breathe-apidoc application to generate RST files according to XML files from Doxygen.
Nevertheless, files /api/classlist.rst
and /api/structlist.rst
are automatically generated at the beginning of compilation to get a better result (class lists per displayed on 3 responsive columns letter by letter).
Managing events pages#
Page /events.rst
is automatically generated at the beginning of compilation to obtain abstracts sorted from the most recent to the older event.
Events files are in /events/
directory. Their names begin by the date written with the format YYYY-MM-DD.
These files always by the definition of a target for cross-referencing, and the title on the third line. The abstract is identified by 2 comments : “.. abstract” and “.. end abstract”.
.. _PoX.14:
Presentation of XLiFE++
#######################
Objectives
**********
.. abstract
This event intends to present the newly released library |xlifepp|
.. end abstract
TikZ figures with sphinxcontrib.tikz extension#
The tikz
directive from sphinxcontrib.tikz
extension (Sphinx TikZ documentation)allows you to write TikZ code or to include files containing TikZ code, through the include
option. sphinxcontrib.tikz
, as configured in XLiFE++ website, will call pdf2svg to generate SVG pictures from TikZ code.
The libs
options allows you to set the TikZ libraries necessary to generate the picture.
The drawback of sphinxcontrib.tikz
extension is that currently it does not manage class
option that is for instance used to manage dark and light modes. So, there is a way to emulate this properly, by using the container
directive:
-
You put TikZ files in the
/_static/pictures/tikz
directory. Here is a sample/_static/pictures/tikz/geo-loop3d.tikz
:\coordinate (p1) at (0,0,0); \coordinate (p2) at (4,0.0); \coordinate (p3) at (4,0,-4); \coordinate (p4) at (0,0,-4); \coordinate (p5) at (0,4,0); \coordinate (p6) at (4,4,0); \coordinate (p7) at (4,4,-4); \coordinate (p8) at (0,4,-4); \coordinate (p9) at (8,2,-2); \draw[thick] (p9) -- (p6) -- (p2) -- (p1) -- (p5) -- (p8) -- (p7) -- (p6) -- (p5) (p7) -- (p9) -- (p2); \draw[thick, dashed] (p1) -- (p4) -- (p3) -- (p2) (p4) -- (p8) (p9) -- (p3) -- (p7); \fill[maincolor] (p1) circle (5pt) node[maincolor, below=1ex] {a}; \fill[maincolor] (p2) circle (5pt) node[maincolor, below=1ex] {b}; \fill[maincolor] (p3) circle (5pt) node[maincolor, above left] {c}; \fill[maincolor] (p4) circle (5pt) node[maincolor, above left] {d}; \fill[maincolor] (p5) circle (5pt) node[maincolor, below right] {e}; \fill[maincolor] (p6) circle (5pt) node[maincolor, below right] {f}; \fill[maincolor] (p7) circle (5pt) node[maincolor, above=1ex] {g}; \fill[maincolor] (p8) circle (5pt) node[maincolor, above=1ex] {h}; \fill[maincolor] (p9) circle (5pt) node[maincolor, right=1ex] {i};
You can see that there is no tikzpicture environment. But you can start the file by the bracket that will be options given to the tikzpicture environment, as you can see for instance in the following generated file
/_static/pictures/tikz/defineMap.tikz
:[scale=4] \draw[->, thick](0,1) -- (0,2); \draw[->, thick](1,0) -- (2,0); \draw[thick, dashed](0,0) -- (0,1); \draw[thick, dashed](0,0) -- (1,0); \draw[very thick, dashed](0,1) -- (1,0); \node[fill=maincolor, inner sep=4pt, ellipse] (a1) at (0.5,0.5) {}; \node[fill=maincolor, inner sep=4pt, ellipse] (a2) at (1.1,1.1) {}; \coordinate (b1) at (1.9,0.6); \coordinate (b2) at (0.8,1.81); \coordinate (b3) at (1.4,1.41); \coordinate (c1) at (2,0.); \coordinate (c2) at (0.,2.); \node[fill=maincolor, inner sep=4pt, ellipse] (d1) at (1.45,1.3) {}; \draw[ultra thick] (1,0) arc (0:90:1); \draw[ultra thick] (2,0) arc (0:90:2); \draw[thick, dashed] (0,0) -- (a1); \draw[->, very thick] (a1) -- (a2); \draw[thick, dashed] (c1) -- (b1); \draw[thick, dashed] (b1) -- (b3); \draw[thick, dashed] (b3) -- (b2); \draw[thick, dashed] (b2) -- (c2); \draw[->, very thick] (a2) -- (d1); \draw (d1) node[above right=0.5ex and 0.5ex] {projection}; \draw (0.7,0.75) node[right=1ex] {circle scaling};
Caution
In XLiFE++ website, options allowed are simple key-values delimited by commas. The forbidden case is for instance the
every path
option that can have several key-values parameters delimited by commas inside the braces. -
You have guidelines concerning colors. It is highly recommended using the following color names, available in light and dark modes:
color name
light mode
dark mode
usage
lightdarkcolor
white
black
to design holes
lightdarknegcolor
black
white
to force border colors when default value is not taken into account (when clipping for instance)
filtercolor
white
gray
to light or to darken other colors
maincolor
XLiFE++
light XLiFE++
secondcolor
dark red
light yellow
thirdcolor
dark blue
light magenta
fourthcolor
dark green
light green
fifthcolor
orange
light orange
-
When generating website, two TikZ files will be generated with the same name but respectively in
/_static/pictures/tikz/light
and/_static/pictures/tikz/dark
directories. Please take a look at thesetup()
method inconf.py
to see how it works. The aim is to add global options to the tikzpicture environment to display code properly (in dark mode, for instance, the default behavior is that paths and texts are colored in white, and that paths are thicked). Here are what have been added to original TikZ code to generate light and dark TikZ files from/_static/pictures/tikz/defineMap.tikz
:[scale=4,font=\Large\itshape,every path/.style={thick}] \definecolor{lightdarkcolor}{RGB}{255,255,255}% \definecolor{filtercolor}{RGB}{255,255,255}% \definecolor{lightdarknegcolor}{RGB}{0,0,0}% \definecolor{maincolor}{RGB}{0,127,127}% \definecolor{secondcolor}{RGB}{127,0,0}% \definecolor{thirdcolor}{RGB}{0,0,127}% \definecolor{fourthcolor}{RGB}{0,127,0}% \definecolor{fifthcolor}{RGB}{255,127,0}%
[scale=4,font=\Large\itshape,every path/.style={draw=white,thick},every node/.style={text=white}] \definecolor{lightdarkcolor}{RGB}{0,0,0}% \definecolor{filtercolor}{RGB}{127,127,127}% \definecolor{lightdarknegcolor}{RGB}{255,255,255}% \definecolor{maincolor}{RGB}{127,255,255}% \definecolor{secondcolor}{RGB}{255,255,127}% \definecolor{thirdcolor}{RGB}{255,127,255}% \definecolor{fourthcolor}{RGB}{127,255,127}% \definecolor{fifthcolor}{RGB}{255,190,63}%
-
You write the following in your RST file:
.. container:: only-light center .. tikz:: :include: /_static/pictures/tikz/light/geo-loop3d.tikz :libs: positioning .. only:: html .. container:: only-dark center .. tikz:: :include: /_static/pictures/tikz/dark/geo-loop3d.tikz :libs: positioning
-
Here is the result. You can play with the dark/light button to see the difference:
Management of bibliography with sphinx-bibtex extension#
2 bibliography files /articles.bib
and /theses.bib
contain all bibliography references with the bibtex format.