From 2fba32dd916c20d5684d3aed8e3c5622c0a1cef4 Mon Sep 17 00:00:00 2001
From: Sébastien Dailly <sebastien@chimrod.com>
Date: Mon, 5 May 2014 21:36:19 +0200
Subject: Update post about graphviz

---
 content/Informatique/rst_graphviz.rst       |  74 ++++++++++---
 content/images/graphe.png                   | Bin 4110 -> 0 bytes
 content/images/graphviz/graphe.png          | Bin 0 -> 11631 bytes
 content/images/graphviz/no.png              | Bin 0 -> 11046 bytes
 content/images/graphviz/options.png         | Bin 0 -> 10627 bytes
 content/resources/rst_graphviz/rst2html.py  |  30 ++++--
 content/resources/rst_graphviz/rst2latex.py | 155 +++++++++++++++++++++++++---
 7 files changed, 224 insertions(+), 35 deletions(-)
 delete mode 100644 content/images/graphe.png
 create mode 100644 content/images/graphviz/graphe.png
 create mode 100644 content/images/graphviz/no.png
 create mode 100644 content/images/graphviz/options.png

diff --git a/content/Informatique/rst_graphviz.rst b/content/Informatique/rst_graphviz.rst
index b2dc477..0682514 100644
--- a/content/Informatique/rst_graphviz.rst
+++ b/content/Informatique/rst_graphviz.rst
@@ -11,7 +11,10 @@ Ajouter graphviz dans les documents restructuredText
 
 .. default-role:: literal
 
-.. image:: |filename|/images/graphe.png
+:2014-05-05:    Je met l'article à jour avec la dernière version du script que
+                j'utilise. J'en profite pour donner un peu plus d'exemples.
+
+.. image:: |filename|/images/graphviz/graphe.png
     :class: floatleft
     :scale: 50
     :alt: Graphe
@@ -31,7 +34,7 @@ la description du graphe, l'application nous génère une image (avec différent
 formats possibles) du graphe. Par exemple, l'image ci contre peut-être
 représentée avec le code suivant :
 
-.. code-block:: C
+.. code-block:: dot
 
     digraph G {
 
@@ -53,26 +56,64 @@ de la génération du document. Pour ça, j'ai créé une nouvelle directive_,
 
 .. _directive: http://docutils.sourceforge.net/docs/ref/rst/directives.html
 
-.. code-block:: rst
+.. list-table::
+    :header-rows: 1
+    :stub-columns: 1
+    :widths:    10 45 45
+
+    *   - Exemple
+        - Code
+        - Résultat
+    *   - Insérer un graphe orienté
+        -
+            .. code-block:: rst
+
+                .. graphviz:: digraph
+
+                    a -> a
+                    a -> b
+                    d -> b
+                    b -> c
+                    c -> b
+
+                    ..
+                    ceci est une légende
+        -
 
-    Voici une image :
+            .. figure:: |filename|/images/graphviz/graphe.png
 
-    .. graphviz::
+                ceci est une légende
 
-        digraph G {
+    *   - Insérer un graphe non-orienté
+        -
+            .. code-block:: rst
 
-            a -> a
-            a -> b
-            d -> b
-            b -> c
-            c -> b
-        }
+                .. graphviz:: graph
 
-deviendra :
+                    a -- a
+                    a -- b
+                    d -- b
+                    b -- c
+                    c -- b
+        -
 
-    Voici une image :
+            .. figure:: |filename|/images/graphviz/no.png
+    *   - Utiliser des options
+        -
+            .. code-block:: rst
 
-    .. image:: |filename|/images/graphe.png
+                .. graphviz:: digraph
+
+                    rankdir = LR;
+
+                    a -> a
+                    a -> b
+                    d -> b
+                    b -> c
+                    c -> b
+        -
+
+            .. figure:: |filename|/images/graphviz/options.png
 
 Pour ceux que ça intéresse, voici le script pour rst2html_ et rst2latex_. Le
 code est similaire, cela ajoute une nouvelle directive qui génère le document à
@@ -80,6 +121,9 @@ l'aide de graphviz, et stocke l'image dans un fichier temporaire, créé dans un
 répertoire *tmp* (qui doit exister avant de lancer la commande). On pourrait
 très facilement l'ajouter à rst2odt en suivant le même principe.
 
+Le script rst2latex génère les images en pdf, il est prévu pour être utilisé
+avec `pdflatex`.
+
 C'est tout, le langage est tellement simple que ça serait dommage de ne pas en
 profiter !
 
diff --git a/content/images/graphe.png b/content/images/graphe.png
deleted file mode 100644
index 9c20f10..0000000
Binary files a/content/images/graphe.png and /dev/null differ
diff --git a/content/images/graphviz/graphe.png b/content/images/graphviz/graphe.png
new file mode 100644
index 0000000..cf50a38
Binary files /dev/null and b/content/images/graphviz/graphe.png differ
diff --git a/content/images/graphviz/no.png b/content/images/graphviz/no.png
new file mode 100644
index 0000000..da3c726
Binary files /dev/null and b/content/images/graphviz/no.png differ
diff --git a/content/images/graphviz/options.png b/content/images/graphviz/options.png
new file mode 100644
index 0000000..4a6805e
Binary files /dev/null and b/content/images/graphviz/options.png differ
diff --git a/content/resources/rst_graphviz/rst2html.py b/content/resources/rst_graphviz/rst2html.py
index ab09012..953ee97 100755
--- a/content/resources/rst_graphviz/rst2html.py
+++ b/content/resources/rst_graphviz/rst2html.py
@@ -8,6 +8,10 @@
 A minimal front end to the Docutils Publisher, producing HTML.
 """
 
+import sys
+reload(sys)
+sys.setdefaultencoding('utf-8')
+
 try:
     import locale
     locale.setlocale(locale.LC_ALL, '')
@@ -28,8 +32,8 @@ description = ('Generates (X)HTML documents from standalone reStructuredText '
 class Graphviz(Figure):
     """ Generate a graphviz image
     """
-    required_arguments = 0
-    optional_arguments = 1
+    required_arguments = 1
+    optional_arguments = 0
     final_argument_whitespace = True
 
     has_content = True
@@ -38,22 +42,36 @@ class Graphviz(Figure):
 
     def run(self):
 
-        text = '\n'.join(self.content)
+        if self.content.count("..") == 0:
+            sep = -1 
+            text = '\n'.join(self.content)
+        else:
+            sep = self.content.index("..")
+            text = '\n'.join(self.content[:sep])
         extension = 'png'
         imageFile = "tmp/%s.%s" % (hash(text), extension)
         if not os.path.exists(imageFile):
-            conversion = subprocess.Popen(['/usr/bin/dot',
+            conversion = subprocess.Popen(['dot',
                 '-T', 'png',
+                "-Gcharset=utf8",
                 '-o', imageFile,
                 ],
                 stdin=subprocess.PIPE
                 )
-            conversion.communicate(text)
+            try:
+                conversion.stdin.write("%s G { \n %s \n}" % (self.arguments[0],
+                    text.encode("utf-8")))
+            except:
+                pass
+            conversion.stdin.close()
             conversion.wait()
 
         self.arguments = [imageFile]
         self.options['scale'] = 50
-        self.content = None
+        if sep == -1:
+            self.content = None
+        else:
+            self.content = self.content[sep+1:]
         return Figure.run(self)
 
 directives.register_directive('graphviz', Graphviz)
diff --git a/content/resources/rst_graphviz/rst2latex.py b/content/resources/rst_graphviz/rst2latex.py
index 9185405..615d2e5 100755
--- a/content/resources/rst_graphviz/rst2latex.py
+++ b/content/resources/rst_graphviz/rst2latex.py
@@ -8,6 +8,10 @@
 A minimal front end to the Docutils Publisher, producing LaTeX.
 """
 
+import sys
+reload(sys)
+sys.setdefaultencoding('utf-8')
+
 try:
     import locale
     locale.setlocale(locale.LC_ALL, '')
@@ -19,7 +23,7 @@ import os.path
 
 from docutils.core import publish_cmdline
 from docutils.parsers.rst import directives
-from docutils.parsers.rst.directives.images import Figure
+from docutils.parsers.rst.directives.images import Figure, Image
 
 description = ('Generates LaTeX documents from standalone reStructuredText '
                'sources. '
@@ -28,11 +32,103 @@ description = ('Generates LaTeX documents from standalone reStructuredText '
                '<http://docutils.sourceforge.net/docs/user/latex.html> for '
                'the full reference.')
 
+DOT2TEX = "dot2tex"
+
+def processContent(node):
+
+    if node.content.count("..") == 0:
+        sep = -1 
+        text = '\n'.join(node.content)
+    else:
+        sep = node.content.index("..")
+        text = '\n'.join(node.content[:sep])
+    extension = 'pdf'
+    pdfFile = "tmp/%s.pdf" % (hash(text))
+
+
+    if not os.path.exists(pdfFile):
+        conversion = subprocess.Popen(['dot',
+            '-T', extension,
+            "-Gcharset=utf8",
+            ],
+            stdin=subprocess.PIPE,
+            stdout=subprocess.PIPE,
+            )
+
+        ps2pdf = subprocess.Popen(['ps2pdf',
+            "-",
+            pdfFile
+            ],
+            stdin = conversion.stdout
+            )
+        conversion.stdin.write("%s G {\n" %
+                node.arguments[0].encode("utf-8"))
+        conversion.stdin.write(text.encode("utf-8"))
+        conversion.stdin.write("\n}")
+        conversion.stdin.close()
+        conversion.stdout.close()
+
+        ps2pdf.wait()
+        conversion.wait()
+        if conversion.returncode != 0:
+            raise node.error(
+                'Error in "%s" directive:\n' % node.name)
+
+    return (sep, pdfFile)
+
+class GraphvizImage(Image):
+    """ Generate a graphviz image
+    """
+    required_arguments = 1
+    optional_arguments = 0
+    final_argument_whitespace = True
+
+    has_content = True
+
+    option_spec = Image.option_spec.copy()
+
+    def run(self):
+
+
+        sep, arguments = processContent(self)
+        self.arguments = [arguments]
+        self.options['scale'] = 66
+        if sep == -1:
+            self.content = None
+        else:
+            self.content = self.content[sep+1:]
+
+        return Image.run(self)
+
 class Graphviz(Figure):
     """ Generate a graphviz image
     """
-    required_arguments = 0
-    optional_arguments = 1
+    required_arguments = 1
+    optional_arguments = 0
+    final_argument_whitespace = True
+
+    has_content = True
+
+    option_spec = Figure.option_spec.copy()
+
+    def run(self):
+
+        sep, arguments = processContent(self)
+        self.arguments = [arguments]
+        self.options['scale'] = 66
+        if sep == -1:
+            self.content = None
+        else:
+            self.content = self.content[sep+1:]
+
+        return Figure.run(self)
+
+
+class Dot2Tex(Figure):
+    """ Generate a graphviz image using dot2tex
+    """
+    required_arguments = 1
+    optional_arguments = 0
     final_argument_whitespace = True
 
     has_content = True
@@ -41,24 +137,55 @@ class Graphviz(Figure):
 
     def run(self):
 
-        text = '\n'.join(self.content)
-        extension = 'png'
-        imageFile = "tmp/%s.%s" % (hash(text), extension)
-        if not os.path.exists(imageFile):
-            conversion = subprocess.Popen(['/usr/bin/dot',
-                '-T', 'png',
-                '-o', imageFile,
+        if self.content.count("..") == 0:
+            sep = -1 
+            text = '\n'.join(self.content)
+        else:
+            sep = self.content.index("..")
+            text = '\n'.join(self.content[:sep])
+        pdfFile = "tmp/%s.pdf" % (hash(text))
+        texFile = "tmp/%s.tex" % (hash(text))
+
+
+        if not os.path.exists(pdfFile):
+            conversion = subprocess.Popen([DOT2TEX,
+                '-c',
+                '-o', texFile,
                 ],
                 stdin=subprocess.PIPE
                 )
-            conversion.communicate(text)
+            conversion.communicate("%s G { \n %s \n}" 
+                    % (self.arguments[0], text))
             conversion.wait()
 
-        self.arguments = [imageFile]
-        self.options['scale'] = 50
-        self.content = None
+            ps2pdf = subprocess.Popen(['pdflatex',
+                '-output-directory', 'tmp',
+                texFile,
+                ],
+                )
+            ps2pdf.wait()
+            if conversion.returncode != 0:
+                raise self.error(
+                    'Error in "%s" directive:\n' % self.name)
+
+        self.arguments = [pdfFile]
+        self.options['scale'] = 66
+        if sep == -1:
+            self.content = None
+        else:
+            self.content = self.content[sep+1:]
+
         return Figure.run(self)
 
+#try:
+#    # Check if dot2tex exists and register the conversion with dot2tex and
+#    # pdftex
+#    subprocess.check_call([DOT2TEX, "-V"])
+#    directives.register_directive('graphviz', Dot2Tex)
+#    directives.register_directive('graphimg', GraphvizImage)
+#except:
+#    # Otherwise use the old graphviz program
 directives.register_directive('graphviz', Graphviz)
+directives.register_directive('graphimg', GraphvizImage)
 
 publish_cmdline(writer_name='latex', description=description)
-- 
cgit v1.2.3