From 4aa4b82000bdfa100155182310a40be3acc86b72 Mon Sep 17 00:00:00 2001 From: Stevie Strickland Date: Sat, 24 Apr 2010 16:22:21 -0400 Subject: [PATCH] Adding the slatex Python module for rubber to contrib. --- collects/meta/contrib/rubber/slatex.py | 152 +++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 collects/meta/contrib/rubber/slatex.py diff --git a/collects/meta/contrib/rubber/slatex.py b/collects/meta/contrib/rubber/slatex.py new file mode 100644 index 0000000000..0623101564 --- /dev/null +++ b/collects/meta/contrib/rubber/slatex.py @@ -0,0 +1,152 @@ +""" +sLaTeX support for Rubber. +""" + +from os import unlink +from os.path import exists, getmtime, join + +import rubber +from rubber import _, msg, Depend, DependLeaf + +def run(doc, env, base): + msg.progress(_("running slatex on %s") % doc.src_base) + if env.execute(["slatex", "-n", base], {}): + msg.error(_("Error executing slatex")) + return 1 + + doc.must_compile = 1 + return 0 + +def slatex_needed(target, srcs): + if not exists(target): + msg.log(_("File %s does not exist") % target, pkg="slatex") + return 1 + for src in srcs: + if getmtime(target) < getmtime(src): + msg.log(_("File %s older than %s") % (target, src), pkg="slatex") + return 1 + return 0 + +class RubberDep (Depend): + # Base is the slatex module + # Target is the autogenerated file (i.e. .Z# + doc.src_base + ".tex") + # Sources is a list of sources on which this file depends + def __init__ (self, mod, target, srcs): + self.mod = mod + self.doc = mod.doc + self.env = mod.doc.env + self.target = target + self.srcs = srcs + + sources = {} + for src in srcs: + sources[src] = DependLeaf(self.env, src) + Depend.__init__(self, self.env, + prods=[target], + sources=sources) + + self.urvater = join(self.doc.src_path, self.doc.src_base + ".tex") + + def run(self): + # We may have been out of date before any dependency was run, + # but by this point we may be up to date since slatex builds + # all the files at once. Otherwise we'll run once per out of + # date generated file. + if slatex_needed(self.target, self.srcs): + run(self.doc, self.env, self.urvater) + +class Module (rubber.rules.latex.Module): + def __init__ (self, doc, dict): + self.base = doc.src_base + self.base_file = join(doc.src_path, doc.src_base + ".tex") + self.final = join(doc.env.path[0], doc.env.final.prods[0]) + self.count = 0 + self.doc = doc + self.env = doc.env + self.file_deps = {} + self.path = doc.src_path + self.preamble = False + + def add_scheme_file(dict, others=[]): + filename = ".Z" + str(self.count) + self.base + ".tex" + path = join(self.path, filename) + deps = [dict["pos"]["file"]] + if others: + deps.extend(others) + self.doc.sources[path] = RubberDep(self, path, deps) + msg.log(_("Marking %s as dependent on %s") % (path, deps), pkg = "slatex") + self.count += 1 + + scheme_macros = ["scheme", "schemeresult"] + + scheme_envs = ["schemedisplay", + "schemeresponse", + "schemebox", + "schemeresponsebox"] + + preamble_macros = ["setspecialsymbol", + "setkeyword", + "defschememathescape"] + + def add_preamble_hook(name): + def h_preamb(dict): + if not self.preamble and slatex_needed(self.final, [self.base_file]): + run(self.doc, self.env, self.base_file) + self.preamble = True + doc.add_hook(name, h_preamb) + + def add_macro_hook(name): + def h_macro(dict): + add_scheme_file(dict) + doc.add_hook(name, h_macro) + + def add_env_hook(name): + beg_env = "begin{%s}" % name + end_env = "end{%s}" % name + def begin_env_hook(dict): + def end_env_hook(dict, self=doc, hooks=doc.hooks): + self.hooks = hooks + self.update_seq() + doc.hooks = { end_env : end_env_hook } + # \scheme, \schemeresult allowed in these. + for macro in scheme_macros: + add_macro_hook(macro) + doc.update_seq() + add_scheme_file(dict) + doc.add_hook(beg_env, begin_env_hook) + + for macro in preamble_macros: + add_preamble_hook(macro) + for macro in scheme_macros: + add_macro_hook(macro) + for environ in scheme_envs: + add_env_hook(environ) + + # handled specially so that we get dependence on the + # file being included as well. + def h_schemeinput(dict): + arg_path = join(self.path, dict["arg"]) + add_scheme_file(dict, others=[arg_path]) + + doc.add_hook("schemeinput", h_schemeinput) + + # schemeregions should generate one file for the entire + # thing, so we shouldn't allow the separate scheme + # hooks like above. + def h_schemeregion(dict, end = "end{schemeregion}"): + def end_env_hook(dict, self=doc, hooks=doc.hooks): + self.hooks = hooks + self.update_seq() + doc.hooks = doc.hooks.copy() + doc.hooks[end] = end_env_hook + for macro in scheme_macros: + if macro in doc.hooks: + del doc.hooks[macro] + for env in scheme_envs: + if ("begin{%s}" % env) in doc.hooks: + del doc.hooks["begin{%s}" % env] + doc.update_seq() + add_scheme_file(dict) + + doc.add_hook("begin{schemeregion}", h_schemeregion) +