racket/collects/meta/contrib/rubber/slatex.py
2010-04-24 16:22:21 -04:00

153 lines
4.3 KiB
Python

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