# # Basic module compiling a file with LaTeX # import os import re import shutil from grubber.texbuilder import LatexBuilder class RunLatex: def __init__(self): self.fig_paths = [] self.index_style = "" self.backend = "pdftex" self.texpost = "" self.texer = LatexBuilder() def set_fig_paths(self, paths): # Assume the paths are already absolute if not(paths): return # Use TEXINPUTS to handle paths containing spaces paths_blank = [] paths_input = [] for p in paths: if p.find(" ") != -1: paths_blank.append(p + "//") else: paths_input.append(p) if paths_blank: texinputs = os.pathsep.join(paths_blank) os.environ["TEXINPUTS"] = os.getenv("TEXINPUTS") + os.pathsep + \ texinputs paths = paths_input # Unixify the paths when under Windows if os.sep != "/": paths = [p.replace(os.sep, "/") for p in paths] # Protect from tilde active char (maybe others?) self.fig_paths = [p.replace("~", r"\string~") for p in paths] def set_bib_paths(self, bibpaths, bstpaths=None): # Just set BIBINPUTS and/or BSTINPUTS if bibpaths: os.environ["BIBINPUTS"] = os.pathsep.join(bibpaths + [os.getenv("BIBINPUTS", "")]) if bstpaths: os.environ["BSTINPUTS"] = os.pathsep.join(bstpaths + [os.getenv("BSTINPUTS", "")]) def set_backend(self, backend): if not(backend in ("dvips", "pdftex", "xetex")): raise ValueError("'%s': invalid backend" % backend) self.backend = backend def get_backend(self): return self.backend def _clear_params(self): self._param_started = 0 self._param_ended = 0 self._params = {} def _set_params(self, line): # FIXME if self._param_ended: return if not(self._param_started): if line.startswith("%%"): self._param_started = 1 return if line.startswith("%%"): self._param_ended = 1 return # Expected format is: '%% \n' p = line.split(" ", 2) self._params[p[1]] = p[2].strip() def compile(self, texfile, binfile, format, batch=1): root = os.path.splitext(texfile)[0] tmptex = root + "_tmp" + ".tex" texout = root + "." + format # The temporary file contains the extra paths f = file(tmptex, "w") if self.fig_paths: paths = "{" + "//}{".join(self.fig_paths) + "//}" f.write("\\makeatletter\n") f.write("\\def\\input@path{%s}\n" % paths) f.write("\\makeatother\n") # Copy the original file and collect parameters embedded in the tex file self._clear_params() input = file(texfile) for line in input: self._set_params(line) f.write(line) f.close() input.close() # Replace the original file with the new one shutil.move(tmptex, texfile) # Build the output file try: self.texer.batch = batch self.texer.texpost = self.texpost self.texer.encoding = self._params.get("latex.encoding", "latin-1") self.texer.options = self._params.get("latex.engine.options") self.texer.lang = self._params.get("document.language") self.texer.set_format(format) self.texer.set_backend(self.backend) if self.index_style: self.texer.index.style = self.index_style self.texer.index.tool = self._params.get("latex.index.tool") self.texer.index.lang = self._params.get("latex.index.language") self.texer.compile(texfile) self.texer.print_misschars() except: # On error, dump the log errors and raise again self.texer.print_errors() raise if texout != binfile: shutil.move(texout, binfile) def clean(self): self.texer.clean() def reinit(self): self.texer.reinit()