diff options
Diffstat (limited to 'bn_django/git_wiki/latex_directive.py')
-rw-r--r-- | bn_django/git_wiki/latex_directive.py | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/bn_django/git_wiki/latex_directive.py b/bn_django/git_wiki/latex_directive.py new file mode 100644 index 0000000..823cc6a --- /dev/null +++ b/bn_django/git_wiki/latex_directive.py @@ -0,0 +1,129 @@ +""" +Implement latex directive. + +""" +import os +import shutil +import sha +import tempfile +import subprocess + +from docutils import nodes +from docutils.parsers.rst.directives import register_directive, flag +from docutils.parsers.rst.roles import register_canonical_role + +from settings import * + +dorawtexstuff = False + +def latex_math(tex,centerize=False): + """ Process `tex` and produce image nodes. """ + if not dorawtexstuff: + image_names = latex_snippet_to_png(tex) + the_nodes = [] + alt = tex + styleclasses = ("equation",) + if tex[:2] =='$$': + centerize=True + if centerize: + styleclasses += ("centered-equ",) + for pageno, name in enumerate(image_names): + the_nodes.append(nodes.image(uri=name, alt=alt, + classes=styleclasses,)) + alt = '' + return the_nodes + else: + return [nodes.raw(tex,tex,format='latex')] + +def latex_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + """ Latex directive. """ + tex = '\n'.join(content) + return latex_math(tex) +latex_directive.content = True + + +def latex_role(role, rawtext, text, lineno, inliner, + options={}, content=[]): + """ Latex role. """ + i = rawtext.find('`') + tex = rawtext[i+1:-1] + return latex_math(tex,), [] + +def register(): + register_directive('latex', latex_directive) + register_canonical_role('latex', latex_role) + register_canonical_role('m', latex_role) + +def call_command_in_dir(app, args, targetdir): + + cwd = os.getcwd() + try: + os.chdir(targetdir) + #print args + #print ' '.join(args) + p = subprocess.Popen(app + ' ' + ' '.join(args), shell=True) + sts = os.waitpid(p.pid, 0) + + # FIXME -- should we raise an exception of status is non-zero? + + finally: + # Restore working directory + os.chdir(cwd) + +latex_template = r''' +\documentclass[12pt]{article} +\pagestyle{empty} +%(prologue)s +\begin{document} +%(raw)s +\end{document} +''' +max_pages = 10 +MAX_RUN_TIME = 5 # seconds +latex_name_template = 'latex2png_%s' +latex = "latex" +dvipng = "dvipng" +latex_args = ("--interaction=nonstopmode", "%s.tex") +dvipng_args = ("-q", "-bgTransparent", "-Ttight", "--noghostscript", "-l%s" % max_pages, "%s.dvi") + +def latex_snippet_to_png(inputtex, prologue=''): + """ Convert a latex snippet into a png. """ + import shutil + + tex = latex_template % { 'raw': inputtex, 'prologue': prologue } + namebase = latex_name_template % sha.new(tex).hexdigest() + dst = namebase + '%d.png' + + tmpdir = tempfile.mkdtemp() + try: + data = open("%s/%s.tex" % (tmpdir, namebase), "w") + data.write(tex) + data.close() + args = list(latex_args) + args[-1] = args[-1] % namebase + res = call_command_in_dir(latex, args, tmpdir) + if not res is None: + # FIXME need to return some sort of error + return [] + args = list(dvipng_args) + args[-1] = args[-1] % namebase + res = call_command_in_dir(dvipng, args, tmpdir) + if not res is None: + # FIXME need to return some sort of error + return [] + + page = 1 + pagenames = [] + while os.access("%s/%s%d.png" % (tmpdir, namebase, page), os.R_OK): + pagename = dst % page + shutil.copyfile("%s/%s%d.png" % (tmpdir, namebase, page), + EQU_FOLDER + pagename) + page += 1 + pagenames.append(EQU_PREFIX + pagename) + finally: + # FIXME do some tidy up here + pass + shutil.rmtree(tmpdir) + return pagenames + |