""" 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)