Rédigeant mon manuscrit, je ne me voyais compiler toutes les cinq minutes mon documents pour voir si je n'ai pas fait une erreur. En effet, détecter une erreur rapidement permet de la corriger facilement surtout que les compilateurs latex et consorts donnent parfois des erreurs peu facile à décrypter.

L'idée est donc de compiler le document automatiquement à chaque dois que je l'enregistre. Une bulle (lib notify) est affichée de manière à prévenir du succès ou de l'échec. Faire ça en python, c'est très simple avec watchdog et pynotify. Quelqu'un avant moi a déjà pensé à faire quelque chose comme ça.

Dans mon cas, je n'utilise pas de makefile. Je fais donc mon appel xelatex directement. J'utilise subprocess.check_call() afin d'avoir le code de retour de xelatex.

Avec pynotify, j'ai une exception gobject.GError qui est parfois levée. Je n'ai pas d'idée de la raison. Si quelqu'un a une idée... sinon, je chercherai plus tard (ça reste Quick and Dirty).


import subprocess
import os
import time

import pynotify
from gobject import GError

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler


class ChangeHandler(FileSystemEventHandler):
    """React to modified .tex files."""
    def on_any_event(self, event):
        """If a file or folder is changed."""
        if event.is_directory:
            return
        if os.path.splitext(event.src_path)[-1].lower() == ".tex":
            pynotify.init("Mon appli python")
            try:
                subprocess.check_call(['xelatex', '-halt-on-error' ,'thesis.tex'])
            except subprocess.CalledProcessError:
                message = pynotify.Notification("Build failed.")
            else:
                message = pynotify.Notification("Build done.")
            try:
                message.show()
            except GError:
                pynotify.uninit()  # methode brute !
                print('Gerror')
                pynotify.init("Mon appli python")



def main():
    handler = ChangeHandler()
    observer = Observer()
    observer.schedule(handler, '.')
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


if __name__ == '__main__':
    main()