Rédiger ses rapports avec rst et sphinx

Posted on 2014-08-13 in Blog

Comme je l'ai déjà évoqué ici et , j'adore les langages à balisage léger. Du coup, j'essaie de les utiliser partout où je peux. Mais de là à rédiger un rapport avec table des matières, pages de garde et glossaire, il y a un pas. Surtout face à la puissance de LaTeX.

J'avais déjà évoqué org-mode ici et pourquoi j'envisageais de l'utiliser en lieu et place de LaTeX, à savoir :

  • Bonne intégration avec Emacs
  • Syntaxe légère
  • Possibilité d'export en LaTeX
  • Possibilité d'insérer du code LaTeX

Mais comme je n'ai pas trouvé de bon support pour org-mode dans Pelican, je m'en suis un peu détourné (je l'utilise toujours pour mes notes) au profit le Restructured Text. Comme ce langage a été conçu pour remplacer LaTeX lors pour la génération HTML de la documentation de python, il est particulièrement puissant. J'ai donc décidé de l'utiliser pour rédiger mon rapport de stage.

Je vais vous présenter tout d'abord Restructured Text (rst) puis sphinx (qui est utilisé pour générer la documentation à partir de fichiers rst) et pourquoi je conseille son utilisation pour un rapport plutôt que juste rst.

Restructured Text

Présentation

La syntaxe est simple. Un bloc de texte constitue un paragraphe. On sépare les paragraphes avec un saut de ligne. On peut écrire en italique et en gras :

*italique* et en **gras**

On peut faire des listes numérotées ou non (attention, les tirets et les dièses doivent être correctement aligné et les sous listes doivent être séparées de la liste par un saut de ligne) :

- item 1
- item 2

  #. Sous-liste numérotée
  #. Un deuxième élément de la sous-liste numérotée

On peut inclure des images :

.. image:: /images/diagramme-fast-LaTeX.png
           :alt: Un diagramme fast réalisé en LaTeX
           :width: 150%

du code :

.. code:: python

          print('Hello World')

Il est tout à fait possible de découper son fichier en plusieurs fichiers plus petits, puis de les inclure avec :

.. include:: fichier.rst

On peut également insérer des fichiers LaTeX avec la directive :

.. raw:: latex
         :file: fast.tex

La syntaxe complète est disponible en ligne. Elle peut paraître déroutante au début, mais on s'y fait et dans l'ensemble, je la trouve très bien faite (de même que la documentation d'ailleurs).

On peut ensuite exporter son fichier en HTML ou LaTeX avec respectivement rst2html et rst2latex.

Rédiger son rapport

Rien de bien fantastique, on entre son texte en respectant la syntaxe, on insère la table des matière avec .. contents:: et on exporte le tout avec rst2latex. On compile ensuite ce fichier avec latexmk. On obtient un fichier Pdf tout ce qu'il y a de plus joli (normal me direz-vous, c'est LaTeX qui l'a fait).

Mais cela ne résout pas tout, comme :

  • Comment fait-on une page de garde ?
  • Comment utilise-t-on une autre police ?
  • Comment insère-t-on un glossaire ?

La réponse aux deux premières questions tient en un mot : template ! En effet, rst2latex dispose d'un argument --template au quel on peut passer un fichier contenant du code LaTeX et des variables rst pour personnaliser le fichier pdf.

Le fichier template de base s'appelle default.tex et se trouve ici : /usr/lib/python3.3/site-packages/docutils/writers/latex2e/default.tex (sur mon PC du moins). Il est assez basique :

$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
\usepackage{fixltx2e} % LaTeX patches, \textsubscript
\usepackage{cmap} % fix search and cut-and-paste in Acrobat
$requirements
%%% Custom LaTeX preamble
$latex_preamble
%%% User specified packages and stylesheets
$stylesheet
%%% Fallback definitions for Docutils-specific commands
$fallbacks$pdfsetup
$titledata
%%% Body
\begin{document}
$body_pre_docinfo$docinfo$dedication$abstract$body
\end{document}

Il n'y plus qu'à le personnaliser avec du code LaTeX pour qu'il réponde à nos besoins :

$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
\usepackage{fixltx2e} % LaTeX patches, \textsubscript
\usepackage{cmap} % fix search and cut-and-paste in Acrobat
\usepackage[raccourcis]{fast-diagram}
\usepackage[french]{babel}
\usepackage{titlesec}
\usepackage[a4paper,left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
$requirements
%%% Custom LaTeX preamble
$latex_preamble
%%% User specified packages and stylesheets
$stylesheet
%%% Fallback definitions for Docutils-specific commands
$fallbacks$pdfsetup
$titledata
%%% Custom font
\usepackage{libertine}
%%% Set numeration
\setcounter{secnumdepth}{3}
%%% Body
\begin{document}
$body_pre_docinfo$docinfo$dedication$abstract$body
\end{document}

Je précise que l'ordre avec lequel vous insérer votre code et les variables est important. Si on met la ligne \usepackage{libertine} (qui change la police) juste après les autres usepackage le choix de ma police sera écrasée par celle de Rst.

Je propose un exemple plus complet en téléchargement (avec notamment une page de garde personnalisée).

On peut également utiliser les options --document-class et --document-options pour personnaliser le document. Il existe bien d'autres options, je vous laisse regarder la sortie de rst2latex -h pour la liste complète.

On générera le fichier .tex avec :

rst2latex
rapport.rst --template=template.tex --documentclass=report --documentoptions=12pt

Et pour le glossaire ? Ce n'est pas possible, faute de syntaxe approprié, directement avec rst. Ça viendra peut être un jour, c'est sur la todo list des dévoleppeurs. C'est là que sphinx entre en jeu.

Sphinx

Présentation

sphinx est un générateur de documentation pour python. Il utilise la syntaxe rst et peut produire des documents HTML, pdf, des pages man, etc. Il propose également des extensions à la syntaxe de base comme term et glossary pour un glossaire et quelques divergences. Par exemple, la table des matières ne se génère plus avec .. contents:: mais avec .. toctree:: et les inclusions de fichier se font avec .. raw::. Typiquement, on utilise un Makefile pour automatiser la génération, Makefile que sphinx est capable de créer tout seul.

Mais rassurez-vous, dans l'ensemble tout fonctionne quasiment comme avec rst. Lorsque je suis passé de rst brut à sphinx, mon seul problème a été l'utilisation des mes entêtes LaTeX personnalisées.

Rédiger son rapport

Il faut tout d'abord initialiser sphinx, avec sphinx-quickstart. Le programme va alors vous poser plusieurs questions pour générer une configuration de base.

Le rapport en lui même se rédige comme sous rst avec les mêmes possibilités d'inclusion de fichiers. Attention toute fois, l'inclusion est relative au Makefile alors qu'aupapravant, elle était relative au fichier d'inclusion.

Lors de mon passage à sphinx, peu importe l'endroit où j'insérais la directive .. toctree:: la table des matières se retrouvait en début de fichier alors que je la voulais après l'introduction et le résumé. Qu'à cela ne tienne, la directive .. raw:: m'a permit d'insérer la commande LaTeX \tableofcontents où je voulais.

.. raw:: latex

         \tableofcontents

Et pour le glossaire alors ? Rien de plus simple :

J'ulitise le :term:`CMS` :term:`Drupal`

.. glossary::

   CMS
     Acronyme de *Content Management System*, soit système de gestion de
     contenu.

   Drupal
     Un des :term:`CMS` les plus connus et réputé. Il est utilisé par de
     nombreuses entreprises et institutions à travers le monde.

Le seul point qui m'a posé problème c'est la configuration. Elle est quasi intégralement géré pour l'export LaTeX par le dictionnaire latex_elements. Par exemple, pour moi :

preamble = r'''\usepackage{fixltx2e} % LaTeX patches, \textsubscript
\usepackage{cmap} % fix search and cut-and-paste in Acrobat
\usepackage[raccourcis]{fast-diagram}
\usepackage{titlesec}
\usepackage[a4paper,left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
%%% Redifined titleformat
\setlength{\parindent}{0cm}
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\newcommand{\hsp}{\hspace{20pt}}
\newcommand{\HRule}{\rule{\linewidth}{0.5mm}}
\titleformat{\chapter}[hang]{\Huge\bfseries\sffamily}{\thechapter\hsp}{0pt}{\Huge\bfseries\sffamily}
%%% Custom font
\usepackage{libertine}
%%% Set numeration
\setcounter{secnumdepth}{3}
'''
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
'papersize': 'a4paper',

# The font size ('10pt', '11pt' or '12pt').
'pointsize': '12pt',

# Babel for french
'babel': '\\usepackage[french]{babel}',

# Additional stuff for the LaTeX preamble.
'preamble': preamble,

# No default title
'maketitle': '',

# No default toc
'tableofcontents': '',
}

La classe du document se spécifie dans la variable latex_documents :

latex_documents = [
  ('rapport', 'Rapport.tex', 'Rapport de stage 2A',
  'Julien Enselme', 'manual'),
]

Les classes habituelles de LaTeX ne sont pas compatibles avec sphinx. Il faut soit utiliser celles par défaut (manual pour un rapport ou how-to pour un article) soit les personnaliser.

Je pense qu'à partir de cet exemple, vous pourrez subvenir à vos besoins facilement. Sinon, vous pouvez toujours poster un commentaire.

Vous trouverez dans la documentation complète toutes des options que je n'ai pas pu vous présenter ici.

Je vous propose également un un fichier de configuration complet

Conclusion

J'espère vous avoir convaincu d'utiliser la puissance et la légèreté de rst et sphinx pour rédiger vos rapports, avec un peu de LaTeX brut par endroit (faute de mieux) en lieu et place des WYSIWYG.

Même si abandonner LaTeX peut faire un peu peur et que la configuration de sphinx est un peu ardue sans exemple complet, je ne regrette pas mon choix et suis bien content d'utiliser rst (même si je dois reconnaître qu'il est dommage que sphinx ne puisse utiliser les classes de base de LaTeX) !