Documentation update: Dropped support for Python 2.4, 2.5, 3.1, and 3.2.
[docutils.git] / sandbox / latex_directive / latex_directive.py
blobfb860988f918aaa276252f44e2e7d5ebbd2f8ca4
1 """
2 Implement latex directive.
4 """
5 import os
6 import shutil
7 import sha
8 import tempfile
9 import subprocess
11 from docutils import nodes
12 from docutils.parsers.rst.directives import register_directive, flag
13 from docutils.parsers.rst.roles import register_canonical_role
16 def latex_math(tex):
17 """ Process `tex` and produce image nodes. """
18 image_names = latex_snippet_to_png(tex)
20 the_nodes = []
21 alt = tex
22 for pageno, name in enumerate(image_names):
24 the_nodes.append(nodes.image(uri=name, alt=alt))
25 alt = ''
27 return the_nodes
30 def latex_directive(name, arguments, options, content, lineno,
31 content_offset, block_text, state, state_machine):
32 """ Latex directive. """
33 tex = '\n'.join(content)
35 return latex_math(tex)
37 latex_directive.content = True
40 def latex_role(role, rawtext, text, lineno, inliner,
41 options={}, content=[]):
42 """ Latex role. """
44 i = rawtext.find('`')
45 tex = rawtext[i+1:-1]
46 return latex_math(tex), []
48 def register():
49 register_directive('latex', latex_directive)
50 register_canonical_role('latex', latex_role)
54 def call_command_in_dir(app, args, targetdir):
56 cwd = os.getcwd()
57 try:
58 os.chdir(targetdir)
59 print args
60 print ' '.join(args)
61 p = subprocess.Popen(app + ' ' + ' '.join(args), shell=True)
62 sts = os.waitpid(p.pid, 0)
64 # FIXME -- should we raise an exception of status is non-zero?
66 finally:
67 # Restore working directory
68 os.chdir(cwd)
70 latex_template = r'''
71 \documentclass[12pt]{article}
72 \pagestyle{empty}
73 %(prologue)s
74 \begin{document}
75 %(raw)s
76 \end{document}
77 '''
78 max_pages = 10
79 MAX_RUN_TIME = 5 # seconds
80 latex_name_template = 'latex2png_%s'
81 latex = "latex"
82 dvipng = "dvipng"
83 latex_args = ("--interaction=nonstopmode", "%s.tex")
84 dvipng_args = ("-bgTransparent", "-Ttight", "--noghostscript", "-l%s" % max_pages, "%s.dvi")
86 def latex_snippet_to_png(inputtex, prologue=''):
87 """ Convert a latex snippet into a png. """
89 tex = latex_template % { 'raw': inputtex, 'prologue': prologue }
90 namebase = latex_name_template % sha.new(tex).hexdigest()
91 dst = namebase + '%d.png'
93 tmpdir = tempfile.mkdtemp()
94 try:
95 data = open("%s/%s.tex" % (tmpdir, namebase), "w")
96 data.write(tex)
97 data.close()
98 args = list(latex_args)
99 args[-1] = args[-1] % namebase
100 res = call_command_in_dir(latex, args, tmpdir)
101 if not res is None:
102 # FIXME need to return some sort of error
103 return []
104 args = list(dvipng_args)
105 args[-1] = args[-1] % namebase
106 res = call_command_in_dir(dvipng, args, tmpdir)
107 if not res is None:
108 # FIXME need to return some sort of error
109 return []
111 page = 1
112 pagenames = []
113 while os.access("%s/%s%d.png" % (tmpdir, namebase, page), os.R_OK):
114 pagename = dst % page
115 shutil.copyfile("%s/%s%d.png" % (tmpdir, namebase, page), pagename)
116 page += 1
117 pagenames.append(pagename)
118 finally:
119 # FIXME do some tidy up here
120 pass
122 return pagenames