K-7.ch
I'm back

Org-mode, exportation LaTeX et Minted

Le 02 oct 2022

Auteur: Plume Mécanique

Tags: emacs orgmode

Comment personnaliser l'exportation de blocs de code depuis Org-mode vers LaTeX et HTML

Avec Org-mode, il est possible d'exporter un document vers le format LaTeX puis PDF. Pour représenter un bloc de code, le document LaTeX utilisera l'environnement verbatim par défaut.

Dans cet article, nous allons voir comment configurer l'utilisation d'un environnement minted. Nous verrons comment configurer Emacs pour l'utiliser et comment le personnaliser.

À propos de Org-mode

Avant de commencer, un petit rappel à propos de Org-mode.

Org-mode est un mode Emacs servant à prendre des notes, rédiger des documents, gérer des listes de tâches, faire de la Programmation lettrée, et bien plus.

Une des fonctionnalités qu'il propose est l'intégration de blocs de code dans un document. Que ce soit dans une note, une tache, un article, un livre, etc.

Ce bloc de code pourra être:

  • Édité dans une fenêtre séparée
  • Exécuté et voir son résultat intégré au document, sous différentes formes (tableau, image, données bruts, etc)
  • Extrait pour être sauvegardé dans un fichier séparé du document
  • Préservé ou masqué, avec le résultat de son exécution, dans une exportation du document vers un autre format, par exemple LaTeX, PDF ou HTML

Une exportation depuis Org-mode vers le format PDF passera par le format LaTeX. Cette exportation nécessite donc la présence de logiciels pouvant compiler du texte au format LaTeX vers le format PDF. Par exemple la suite TeX Live.

Bloc de code dans un document Org-mode

Dans un document Org-mode, qui n'est autre qu'un simple fichier texte, on peut déclarer un bloc de code avec les deux lignes de texte suivantes:

#+begin_src

#+end_src

Ces lignes indiqueront les limites du bloc. On peut ensuite indiquer le langage du code source en l'écrivant juste après le #+begin_src, sur la même ligne que ce dernier. Maintenant, il ne reste plus qu'à écrire le code source entre les deux lignes marquant les limites du bloc.

Voici un exemple de bloc de code Python:

#+begin_src python
  #!/usr/bin/env python

  import os
  from pprint import pprint


  def main():
      'Set and print some variables'
      message = 'This is a message to be printed'
      number = 123
      print(message)
      print(f'And now, a number: {number}')


  if __name__ == '__main__':
      main()
#+end_src

On peut indiquer d'autres options que le langage, mais cela va au delà de l'objectif de cet article. Pour en savoir plus sur les blocs de code avec Org-mode, je vous renvoie à son manuel d'utilisation.

À propos de Minted

Minted est un environnement LaTeX qui sert à représenter des blocs de code dans un document LaTeX.

Il utilise Pygments pour la coloration syntaxique et propose de nombreuses options. Pour plus d'information, je vous invite à lire sa documentation officielle.

Logiciels à installer

Nous allons devoir installer plusieurs logiciels.

En plus d'Emacs, nous aurons besoin d'une suite de compilation LaTeX ainsi que du logiciel latexmk.

Pour la suite de compilation LaTeX, j'utilise TeX Live.

Il vous faudra également le paquets LaTeX nommé texlive-minted.

Enfin, Minted, pour la coloration syntaxique, utilise le paquets Python nommé Pygments. Il faudra donc l'installer.

Je vous conseille de les installer depuis le gestionnaire de paquets de votre distribution GNU/Linux. Pour TeX Live, certaines distributions proposent des paquets texlive-scheme-full ou texlive-full. Je vous conseille d'installer ceux-ci afin d'avoir tout ce qui vous sera nécessaire.

Configuration de Emacs pour utiliser minted

Nous allons maintenant pouvoir configurer Emacs, afin de lui dire d'utiliser l'environnement minted pour les blocs de code.

Toute la configuration devra être écrite dans l'un des deux fichiers de configuration d'Emacs:

  • Soit dans votre fichier ~/.emacs
  • Soit dans votre fichier ~/.emacs.d/init.el

Pour commencer, assurons-nous que ox-latex est chargé ajoutant cette ligne dans votre configuration:

(require 'ox-latex)

Ceci fait, indiquons à Org-mode que nous voulons utiliser l'environnement minted lors de l'export vers LaTeX. Pour ça, ajoutons ces 2 lignes dans votre configuration:

(setq org-latex-listings 'minted)
(add-to-list 'org-latex-packages-alist '("" "minted"))

La première ligne indique à Org-mode d'utiliser l'environnement minted pour les blocs de code exportés vers LaTeX. La seconde demande d'ajouter le paquet LaTeX minted au début des documents LaTeX lors de l'exportation.

Nous devons ensuite indiquer au compilateur LaTeX utilisé que nous autorisons l'exécution d'un logiciel externe. Ceci est nécessaire pour que minted puisse utiliser Pygments. Pour ça, ajoutons cette ligne dans la configuration:

(setq org-latex-pdf-process
      '("%latex -shell-escape -interaction nonstopmode -output-directory %o %f"))

Ceci définira la commande suivant pour la compilation de document LaTeX:

%latex -shell-escape -interaction nonstopmode -output-directory %o %f

Voici les détails de la commande:

  • %latex: Sera remplacé par le compilateur LaTeX utilisé
  • -shell-escape: Autorise l'exécution d'un logiciel externe
  • -interaction nonstopmode: Définit l'interaction en mode non-stop
  • -output-directory %o: Définit le dossier de sortie comme étant le même que le dossier du fichier source (chemin relatif)
  • %f: Sera remplacé par le chemin relatif vers le fichier LaTeX à compiler

Premier essai d'exportation avec Minted

Nous pouvons maintenant exporter l'exemple définit plus tôt. Voici à quoi ressemble notre bloc de code une fois exporté en LaTeX:

\begin{minted}[]{python}
#!/usr/bin/env python

import os
from pprint import pprint


def main():
    'Set and print some variables'
    message = 'This is a message to be printed'
    number = 123
    print(message)
    print(f'And now, a number: {number}')


if __name__ == '__main__':
    main()
\end{minted}

Et, quelque part au début du document .tex, on retrouve:

\usepackage{minted}

Et voici à quoi ressemble le bloc de code dans le document PDF: Bloc de code exporté avec des couleurs

Personnaliser l'exportation

Le paquet LaTeX minted propose de nombreuses options. Je ne vais pas toutes les couvrir ici, mais me concentrer sur 4 d'entre elles:

  • Ajouter et personnaliser des numéros de ligne à côté du bloc de code
  • Ajouter des retours à la ligne automatiques pour les lignes trop longues
  • Ajouter un cadre de décoration
  • Définir l'espace entre le cadre et le code

On peut définir ces options pour chaque bloc individuellement ou globalement.

Options par bloc

Lorsqu'on déclare un bloc de code dans du texte au format Org, il est possible de spécifier des paramètres appliqués uniquement lors d'une exportation en LaTeX. Pour ça, il faut ajouter la ligne #+ATTR_LATEX: avant le bloc de code.

Cette nouvelle ligne accepte des paramètres sous la forme :clé valeur. Si on utilise la clé options, on peut indiquer comme valeur les options qui seront passés à l'environnement minted.

Par exemple, si on veut avoir les numéros de ligne à gauche du bloc de code, il faut passer l'option linenos=true à l'environnement minted.

Pour cela, écrivez votre bloc de code au format Org comme ceci:

#+ATTR_LATEX: :options linenos=true
#+begin_src python
  #!/usr/bin/env python

  import os
  from pprint import pprint


  def main():
      'Set and print some variables'
      message = 'This is a message to be printed'
      number = 123
      print(message)
      print(f'And now, a number: {number}')


  if __name__ == '__main__':
      main()
#+end_src

Voici le résultat, après exportation, au format LaTeX:

\begin{minted}[,linenos=true]{python}
#!/usr/bin/env python

import os
from pprint import pprint


def main():
    'Set and print some variables'
    message = 'This is a message to be printed'
    number = 123
    print(message)
    print(f'And now, a number: {number}')


if __name__ == '__main__':
    main()
\end{minted}

Et voici le résultat au format PDF: Bloc de code avec couleurs et numéros de lignes

Il est possible de spécifier plusieurs options en tant que valeur associée à la clé options. Il faut séparer les options avec le caractère ,.

Par exemple, si on souhaite les numéros de lignes et un cadre d'une simple ligne à gauche, voici à quoi ressemble notre bloc de code au format Org:

#+ATTR_LATEX: :options linenos=true,frame=leftline
#+begin_src python
  #!/usr/bin/env python

  import os
  from pprint import pprint


  def main():
      'Set and print some variables'
      message = 'This is a message to be printed'
      number = 123
      print(message)
      print(f'And now, a number: {number}')


  if __name__ == '__main__':
      main()
#+end_src

Voici le résultat au format LaTeX une fois exporté:

\begin{minted}[,linenos=true,frame=leftline]{python}
#!/usr/bin/env python

import os
from pprint import pprint


def main():
    'Set and print some variables'
    message = 'This is a message to be printed'
    number = 123
    print(message)
    print(f'And now, a number: {number}')


if __name__ == '__main__':
    main()
\end{minted}

Et voici le rendu au format PDF: Bloc de code avec couleur, numéros de lignes et bar verticale à gauche

Options appliqués à toutes exportations

Il est possible de définir des options qui seront présentes sur tous les blocs de code exportés du format Org au format LaTeX. Ces options seront cumulées aux options définit par blocs.

Pour cela, il faut définir la valeur de la variable org-latex-minted-options dans la configuration d'Emacs. Il s'agit d'une liste d'associations: Une liste dont chaque élément est une liste de 2 éléments. Ces listes de 2 éléments sont des associations entre l'option qui sera passé à minted et la valeur de cette option.

Par exemple, si on veut juste activer les numéros de lignes sur toutes les exportations de bloc de code, on ajoute ceci à la configuration d'Emacs:

(setq org-latex-minted-options
      '(("linenos" "true")))

Dans cet exemple, org-latex-minted-options est une liste d'un seul élément. Cet élément est une liste associant l'option linenos avec la valeur true. Ceci se traduira, lors d'une exportation au format LaTeX, par ceci:

\begin{minted}[,linenos=true]{python}
#!/usr/bin/env python

import os
from pprint import pprint


def main():
    'Set and print some variables'
    message = 'This is a message to be printed'
    number = 123
    print(message)
    print(f'And now, a number: {number}')


if __name__ == '__main__':
    main()
\end{minted}

Autre exemple: Si on souhaite activer les numéros de lignes ainsi qu'un cadre d'une simple ligne à gauche, voici ce qu'il faut écrire dans la configuration d'Emacs:

(setq org-latex-minted-options
            '(("frame" "leftline") ("linenos" "true")))

On a ici la variable org-latex-minted-options qui est une liste de 2 éléments. Le premier est une liste associant l'option frame avec la valeur leftline et le second élément est une liste associant l'option linenos avec la valeur true.

Quatre exemples d'options pour minted

Voici quatre exemples d'options dont je parlais plus haut:

  • Numéros de ligne
  • Retours à la ligne automatiques pour les lignes trop longues
  • Cadre de décoration
  • Rendu des formules au format LaTeX dans les commentaires
  • Style

Numéros de lignes

Pour les numéros de lignes, on utilise l'option linenos. Elle est de type boolean, sa valeur est donc true ou false. true l'active et false la désactive.

On peut utiliser l'option stepnumber pour indiquer l’intervalle auquel les numéros de lignes apparaissent. Par exemple stepnumber=5 pour avoir les numéros toutes les 5 lignes. Si on souhaite toujours numéroter la première ligne, on peut spécifier l'option numberfirstline=true.

L'option numbers ajoute également les numéros de lignes, mais permet de spécifier où on souhaite les voir. Les valeurs possibles sont: left, right, both et none.

Retour à la ligne automatique

Pour activer les retours à la ligne automatiques quand une ligne est trop longue, on peut utiliser l'option breaklines. Sa valeur est de type boolean.

Par défaut, les lignes sont "cassées" uniquement sur un caractère espace et le caractère (flèche droite) est inséré avant chaque nouvelle ligne créée automatiquement.

Voici le rendu par défaut d'une ligne trop longue automatiquement "cassée": Bloc de code avec une longue chaine de caractère

Cadre de décoration

Pour définir un cadre de décoration, on peut spécifier l'option frame. Ses valeurs possibles sont none, leftline, topline, bottomline, lines et single. lines ajoute une ligne au-dessus et en dessous uniquement. single ajoute une ligne tout autour du bloc.

On peut définir la distance entre le code et le cadre avec l'option framesep et la largeur de la ligne avec l'option framerule. Ces 2 options acceptent comme valeur des dimensions au format LaTeX, par exemple 0.4pt ou \fboxsep.

Rendu des formules au format LaTeX dans les commentaires

Si dans les commentaires de votre code vous avez écrit des formules de math au format LaTeX, vous pouvez activer leur rendu avec l'option mathescape. Sa valeur est de type boolean. Une fois cette option activée, la version PDF de votre bloc de code aura une belle formule de math.

Prenons par exemple le code Python suivant:

# Return $\sum_{i=1}^{n}i$
def sum_from_one_to(n):
    range_of_numbers = range(1, n + 1)
    return sum(range_of_numbers)

Voici, avec l'option mathescape, le rendu au format PDF: Bloc de code avec formule de math dans les commentaires

Style

Pygments propose plusieurs styles de rendu. Je vous invite à voir la section style du site web officiel pour en connaître la liste.

Si vous voulez utiliser un style autre que celui par défaut, par exemple rrt, vous pouvez l'indiquer avec l'option style. Sa valeur est le non du style choisi.

Il est à noter que le style choisi n'a aucun effet sur la couleur de fond du bloc de code. Par défaut, la couleur de fond est absente et sera donc celle du document. Si vous voulez définir manuellement une couleur de fond, il vous faudra utiliser l'option bgcolor. Attention, cette option n'accepte que des couleurs déjà définies par une macro LaTeX. Cette limitation vient du paquet LaTeX minted.

Pour définir une nouvelle couleur dans votre document LaTeX, il faut ajouter ces 2 lignes au début de votre document Org:

#+LATEX_HEADER_EXTRA: \usepackage{xcolor}
#+LATEX_HEADER_EXTRA: \definecolor{bg}{HTML}{282828}

Ceci ajoutera à votre document LaTeX:

\usepackage{xcolor}
\definecolor{bg}{HTML}{282828}

La première ligne importera le paquet xcolor et le second définira une couleur du nom de bg. La définition utilise le format HTML avec une couleur 282828.

Maintenant, pour utiliser cette couleur et définir le style sur votre bloc de code, il faut déclarer cette ligne #+ATTR_LATEX: au-dessus de votre bloc:

#+ATTR_LATEX: :options bgcolor=bg,style=monokai

Conclusion et aller plus loin

Minted propose un magnifique rendu pour vos blocs de code et fournit de nombreuses options pour personnaliser leurs apparences. Il y aurait beaucoup à dire sur les options de Minted. Je vous invite à lire sa documentation officielle.

LaTeX est un format de document très riche et polyvalent, mais parfois un peu difficile à lire et à écrire pour un humain. C'est pour cela que je préfère écrire mes documents au format Org-mode, puis les exporter au format LaTeX puis PDF. Mais si on souhaite personnaliser l'apparence du document final, il faut connaître un peu de LaTeX. Au moins de quoi configurer l'exportation de notre document dans ce format.

Org-mode est un outil extrêmement efficace, tout comme Emacs. Je prévois d'écrire plusieurs articles à leurs sujets. En attendant, je vous invite à lire leurs documentations officielles:

Si vous utilisez déjà Emacs, vous pouvez accéder à tout moment au manuel de Org-mode et Emacs avec le raccourci Ctrl-h i.