aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Kuhnert2009-10-13 13:36:17 +0000
committerSebastian Kuhnert2009-10-13 13:36:17 +0000
commit4123f6cc94167ccad7a91dc77cad07b52d0101f7 (patch)
tree8f9653c93a3bba8d8404a157c922fc49089fb698
parent6affa2159dea7c1a2292f197f3c27bdcc6ab2f68 (diff)
downloadexercisesheets-4123f6cc94167ccad7a91dc77cad07b52d0101f7.tar.gz
exercisesheets-4123f6cc94167ccad7a91dc77cad07b52d0101f7.tar.bz2
exercisesheets-4123f6cc94167ccad7a91dc77cad07b52d0101f7.zip
-rwxr-xr-xtexall955
1 files changed, 0 insertions, 955 deletions
diff --git a/texall b/texall
deleted file mode 100755
index 8a6c496..0000000
--- a/texall
+++ /dev/null
@@ -1,955 +0,0 @@
-#!/usr/bin/env python
-
-from optparse import OptionParser
-import sys
-import os
-import os.path
-import pty
-import re
-import select
-import subprocess
-import fnmatch
-import dircache
-import termios
-import signal
-
-class TexallOptionParser(OptionParser):
- def __init__(self):
- OptionParser.__init__(self,
- usage="%prog [options] DIR/FILE",
- version="%prog $Id$",
- description="Call LaTeX and friends to typeset all tex files in DIR/FILE. By default up-to-date files are skipped. Care is taken to run all required commands until the result is stable. By default, pdflatex is used, but use of pstricks forces dvi->ps->pdf. The utility program rmligs ist used to improve output for german language texts. Use \"texall -Sqfi batchmode file.tex\" to simulate the behaviour of (pdf)latex in non-interactive mode (useful for emacs).")
- self.add_option("-n", "--dry-run",
- action="store_false", dest="act", default=True,
- help="do not run any program")
- self.add_option("-f", "--force",
- action="store_true", dest="force", default=False,
- help="regenerate up-to-date files")
- self.add_option("-N", "--non-recursive",
- action="store_false", dest="recurse", default=True,
- help="disable recursion into subdirectories")
- self.add_option("-s", "--summary", dest="summary",
- help="summarise failures and processed files at the end of the run (one of failures (default), files, both, no)",
- choices=("no","files","failures","both"), default="failures")
- self.add_option("-v", "--verbose",
- action="count", dest="verbosity", default=1,
- help="explain what is going on")
- self.add_option("-q", "--quiet",
- action="store_const", dest="verbosity", const=0,
- help="suppress progress reports")
- self.add_option("-o", "--show-output",
- action="store_true", dest="showoutput", default=False,
- help="show the output of the called programs")
- self.add_option("-i", "--interaction",
- dest="interactionmode", choices=("batchmode", "nonstopmode", "scrollmode", "errorstopmode"),
- help="control the behaviour of latex (on of batchmode (default), nonstopmode (default for -o), scrollmode, errorstopmode)")
- self.add_option("-I", "--ignore",
- action="store", dest="ignorepattern", default=".*vorlage|\\.\\#|.*-rmligs\\.tex$",
- help="regular expression of filenames to ignore")
- self.add_option("-P", "--required-pattern",
- action="store", dest="requiredpattern", default='^\\\\documentclass|^%%% TeX-master: t',
- help="regular expression that must match the file content")
- self.add_option("-T", "--preserve-tempfiles",
- action="store_false", dest="deletetempfiles", default=True,
- help="preserve temporary files (default: delete)")
- self.add_option("-K", "--no-kpathsea",
- action="store_true", dest="nokpse", default=False,
- help="do not call kpsewhich (might be faster)")
- self.add_option("-S", "--single-run",
- action="store_true", dest="singlerun", default=False,
- help="stop after the first LaTeX run, no matter if finished")
-
- def parse_args(self, args=None, values=None):
- options, arguments = OptionParser.parse_args(self, args, values)
-
- # provide default for interactionmode:
- if options.interactionmode == None:
- if options.showoutput:
- options.interactionmode = "nonstopmode"
- else:
- options.interactionmode = "batchmode"
-
- return options, arguments
-
-class AnalyserData:
- def __init__(self, name, filetype):
- self.name = name
- self.filetype = filetype
-
-class Analyser:
- """Abstract class for analysing of program output and file content"""
-
- def __init__(self, d):
- """Instance creation.
-
- d -- dictionary to store data in"""
- self.d = d
-
- def parse(self, text):
- """parse text and change own state accordingly.
-
- text -- the filecontent or line to analyse"""
- raise NotImplementedError
-
- def merge(self, d):
- """merge information gathered from an included file.
-
- d -- dictionary with information gathered from the included file"""
- raise NotImplementedError
-
- def finish(self, dirname):
- """final steps after all dependecy file information hat been merged.
-
- Only executed if this data object belongs to a main .tex file.
-
- dirname -- directory of current job"""
- pass
-
-class AnalyseTexRequired(Analyser):
- def __init__(self, d):
- d.required = False
- Analyser.__init__(self,d)
- def parse(self, text):
- if re_required.search(text):
- self.d.required = True
- def merge(self, d):
- self.d.required |= d.required
-
-class AnalyseTexDependencies(Analyser):
- def __init__(self, d):
- d.deps = []
- d.grfdeps = []
- Analyser.__init__(self, d)
- def parse(self, text):
- for m in re_inputinclude.finditer(text):
- self.d.deps.append((m.group(2), (".tex", "")))
- m = re_documentclass.search(text)
- if m:
- cls = m.group(2)
- self.d.deps.append((cls, (".cls", "")))
- for m in re_usepackage.finditer(text):
- stys = m.group(2)
- for sty in re_commawhitespace.split(stys):
- self.d.deps.append((sty, (".sty", "")))
- for m in re_usetheme.finditer(text):
- themes = m.group(3)
- ttype = m.group(1)
- for theme in re_commawhitespace.split(themes):
- self.d.deps.append(("beamer%stheme%s"%(ttype, theme), (".sty",)))
- for m in re_graphics.finditer(text):
- self.d.grfdeps.append(m.group(2))
- def merge(self, d):
- self.d.deps.extend(d.deps)
- self.d.grfdeps.extend(d.grfdeps)
- def finish(self, dirname):
- if hasattr(self.d, "needsPS"):
- if self.d.needsPS:
- for f in self.d.grfdeps:
- self.d.deps.append((f, (".eps", ".jpg", ".png", "")))
- else:
- for f in self.d.grfdeps:
- self.d.deps.append((f, (".pdf", ".jpg", ".png", "")))
- expandeddeps = []
- for dep, extlist in self.d.deps:
- if extlist == None:
- expandeddeps.append((dep, extlist))
- else:
- try:
- expandeddeps.append((texpath(dirname, dep, extlist=extlist), None))
- except ValueError, e:
- if opts.verbosity > 2:
- error(self.d.name, "ignoring dependency: %s"%e, warning=True)
- self.d.deps = expandeddeps
-
-class AnalyseTexBibfiles(Analyser):
- def __init__(self, d):
- d.bibfiles = []
- Analyser.__init__(self, d)
- def parse(self, text):
- for m in re_bibliography.finditer(text):
- bibs = m.group(1)
- for bib in re_commawhitespace.split(bibs):
- if bib[-8:] != "-blx.bib" and bib[-4:] != "-blx":
- self.d.bibfiles.append(bib)
- def merge(self, d):
- self.d.bibfiles.extend(d.bibfiles)
- def finish(self, dirname):
- bibpaths = []
- for bib in self.d.bibfiles:
- try:
- bibpath = texpath(dirname, bib, pathtype="bib",progname="bibtex")
- bibpath = strippath(bibpath, dirname)
- self.d.deps.append((bibpath, None))
- bibpaths.append(bibpath)
- except ValueError, e:
- error(self.d.name, str(e), warning=True)
- bibpaths.append(bib)
- pass
- self.d.bibfiles = bibpaths
-
-class AnalyseTexNeedsPs(Analyser):
- def __init__(self, d):
- d.needsPS = False
- Analyser.__init__(self, d)
- def parse(self, text):
- if re_needsps.search(text):
- self.d.needsPS = True
- def merge(self, d):
- self.d.needsPS |= d.needsPS
-
-class AnalyseTexRmligs(Analyser):
- def __init__(self, d):
- d.rmligs = False
- Analyser.__init__(self, d)
- def parse(self, text):
- if re_rmligs.search(text):
- self.d.rmligs = True
- def merge(self, d):
- self.d.rmligs |= d.rmligs
-
-class AnalyseTexDatatool(Analyser):
- def __init__(self, d):
- d.DTLdeps = []
- Analyser.__init__(self, d)
- def parse(self, text):
- for m in re_DTLdep.finditer(text):
- self.d.DTLdeps.append((m.group(2), None))
- def merge(self, d):
- self.d.DTLdeps.extend(d.DTLdeps)
- def finish(self, _):
- self.d.deps.extend(self.d.DTLdeps)
-
-texanalysers = (AnalyseTexRequired, AnalyseTexDependencies, AnalyseTexBibfiles, AnalyseTexNeedsPs, AnalyseTexRmligs, AnalyseTexDatatool)
-
-class AnalyseLogErrors(Analyser):
- def __init__(self, d):
- d.errors = False
- Analyser.__init__(self, d)
- def parse(self, text):
- if re_error.search(text):
- self.d.errors = True
-
-class Request():
- def __init__(self, progname, priority=0, invocation=None, reason=None):
- self.progname = progname
- self.priority = priority
- self.invocation = invocation
- self.reason = reason
-
-class AnalyseLogRequests(Analyser):
- def __init__(self, d):
- d.requests = {}
- Analyser.__init__(self, d)
- def addrequest(self, name, priority, invocation=None, reason=None):
- if self.d.requests.has_key(name):
- oldreq = self.d.requests[name]
- if oldreq.priority < priority:
- oldreq.priority = priority
- if reason:
- oldreq.reason = reason
- if invocation:
- oldreq.invocation = invocation
- else:
- if not oldreq.reason:
- oldreq.reason = reason
- if not oldreq.invocation:
- oldreq.invocation = invocation
- else:
- self.d.requests[name] = Request(name, priority, invocation, reason)
- def parse(self, text):
- for m in re_logmatcher.finditer(text):
- if m.group() == 'LaTeX Warning: There were undefined references.':
- self.addrequest("latex", 0, reason=" (because of undefined references)")
- elif m.group() == 'LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.':
- self.addrequest("latex", 0, reason=" (because of changed labels)")
- elif m.group()[-5:] == ".bbl.":
- self.addrequest("bibtex", 1, reason=" (because of missing .bbl)")
- self.addrequest("latex", 0, reason=" (because of updated .bbl)")
- elif m.group(1)!=None:
- self.addrequest(m.group(2), int(m.group(1)))
- elif m.group(3)!=None:
- pri = int(m.group(3))
- progname = m.group(4)
- binary = None
- options = []
- infile = None
- for l in re_longreq.finditer(m.group(5)):
- if l.group(1) == "infile":
- infile = l.group(2)
- elif l.group(1) == "option":
- options.extend(l.group(2).split(" "))
- elif l.group(1) == "binary":
- binary = l.group(2)
- if binary not in ("bibtex", "bibtex8"):
- error(self.d.name, "ignoring request to run %s for security reasons"%binary, warning=True)
- continue
- options[:0] = [binary]
- if binary == "bibtex8":
- options[1:1] = [ "--wolfgang" ]
- if infile != None:
- options.append(infile)
- self.addrequest(progname, pri, invocation=tuple(options))
- def finish(self, _):
- if self.d.errors:
- self.addrequest("latex", 0, reason=" (because of errors in .log file)")
- reqdict=self.d.requests
- maxpri=0
- for req in reqdict.itervalues():
- if req.priority > maxpri:
- maxpri = req.priority
- reqlist = []
- for pri in range(maxpri, -1 , -1):
- for req in reqdict.itervalues():
- if req.priority == pri:
- reqlist.append(req)
- self.d.requests = reqlist
-
-loganalysers = (AnalyseLogErrors, AnalyseLogRequests)
-
-analysecachedir = None
-analysecache = {}
-
-def analyseFile(dirname, filename, analyserclasses, parsetype, fulltext=False, cache=False, recurse=None, recursesystemfiles=False):
- global analysecachedir, analysecache
- if dirname != analysecachedir:
- analysecachedir = dirname
- analysecache = {}
- pathname = os.path.join(dirname, filename)
- if cache and (parsetype, pathname) in analysecache:
- return analysecache[(parsetype, pathname)]
- data = AnalyserData(pathname, parsetype)
- analysers = []
- for analyser in analyserclasses:
- analysers.append(analyser(data))
- try:
- f = open(pathname, "r")
- if fulltext:
- text = f.read()
- if parsetype == "tex":
- text = re_texcomment.sub("", text)
- for a in analysers:
- a.parse(text)
- else:
- for line in f:
- for a in analysers:
- a.parse(line)
- except IOError, e:
- error(pathname, "could not be analysed: %s"%e)
- else:
- f.close()
- if hasattr(data, "deps") and (recurse
- or (recurse==None
- and hasattr(data, "required")
- and data.required)):
- # recurse:
- for dep, extlist in data.deps:
- try:
- deppath = texpath(dirname, dep, extlist=extlist)
- except ValueError, e:
- continue
- if (not recursesystemfiles) and re_systemfile.search(deppath): # skip system files
- continue
- depname = strippath(deppath, dirname)
- depdata = analyseFile(dirname, depname, analyserclasses, parsetype, fulltext, cache, True, recursesystemfiles)
- for a in analysers:
- a.merge(depdata)
- if (hasattr(data, "required") and data.required) or parsetype == "log":
- for a in analysers:
- a.finish(dirname)
- if cache:
- analysecache[(parsetype, pathname)] = data
- return data
-
-def analyseTex(dirname, filename):
- return analyseFile(dirname, filename, texanalysers, "tex", fulltext=True, cache=True)
-
-def analyseLog(dirname, filename):
- return analyseFile(dirname, filename, loganalysers, "log", fulltext=True, cache=False)
-
-binpath = os.path.expandvars("$PATH")
-if binpath == "$PATH":
- binpath = os.path.defpath
-binpath = binpath.split(os.path.pathsep)
-def isinpath(name):
- for p in binpath:
- if os.path.exists(os.path.join(p, name)):
- return True
- return False
-
-if isinpath("rmligs"):
- rmligs_name = "rmligs"
-elif isinpath("rmligs-german"):
- rmligs_name = "rmligs-german"
-else:
- rmligs_name = ""
- error("rmligs", "Command not found. Please install rmligs (or rmligs-german) for optimal results", warning=True)
-
-kpsecache = {}
-kpseproc = {}
-haskpseinter = isinpath("kpseinter")
-def kpselookup(lookupname, pathtype, progname):
- if not kpsecache.has_key((pathtype,progname)):
- kpsecache[(pathtype,progname)] = {}
- cache = kpsecache[(pathtype,progname)]
- if cache.has_key(lookupname):
- if cache[lookupname]:
- return cache[lookupname]
- else:
- raise ValueError("not found by kpathsea: %s"%lookupname)
- if not haskpseinter:
- kpse=subprocess.Popen(["kpsewhich", "-format", pathtype, "-progname", progname, lookupname],
- stdout=subprocess.PIPE,
- cwd="/")
- (out,err)=kpse.communicate()
- if kpse.wait() == 0:
- pathname = out[:-1]
- cache[lookupname] = pathname
- return pathname
- else:
- cache[lookupname] = None
- raise ValueError("not found by kpathsea: %s"%lookupname)
- else:
- if kpseproc.has_key((pathtype, progname)):
- proc, master = kpseproc[(pathtype, progname)]
- os.write(master, lookupname + "\n")
- else:
- master, slave = pty.openpty()
-
- #turn off echo
- attr = termios.tcgetattr(slave)
- attr[3] = attr[3] & ~termios.ECHO
- termios.tcsetattr(slave, termios.TCSANOW, attr)
-
- proc = subprocess.Popen(["kpseinter", "--interactive",
- "-format", pathtype,
- "-progname", progname,
- lookupname],
- stdout=slave,
- stdin=slave,
- cwd="/")
- kpseproc[(pathtype, progname)] = proc, master
- answer = os.read(master, 1024)
- while answer and answer[-1] in ("\n", "\r"):
- answer = answer[:-2]
- if answer != "":
- cache[lookupname] = answer
- return answer
- else:
- cache[lookupname] = None
- raise ValueError("not found by kpathsea: %s"%lookupname)
-
-def texpath(dirname,filename,pathtype="tex",progname="latex",extlist=("",)):
- if extlist == None:
- return filename
- filename = os.path.expanduser(filename)
- # first try files in current directory
- if pathtype=="bib" and extlist==("",):
- extlist=(".bib", "")
- for ext in extlist:
- if os.path.exists(os.path.join(dirname,filename+ext)):
- return filename+ext
- if opts.nokpse:
- raise ValueError("file not found, not using kpsewhich: %s (extensions: %r)"%(filename, extlist))
- # call kpsewhich to locate the file
- for ext in extlist:
- try:
- path = kpselookup(filename + ext, pathtype, progname)
- return path
- except ValueError:
- pass
- raise ValueError("not found by kpathsea: %s (extensions: %r)"%(filename,extlist))
-
-errors = []
-procfiles = []
-
-errstr = {False: "ERROR", True: "WARNING"}
-def error(file, desc, warning=False):
- msg = "%s: %s: %s"%(errstr[warning], os.path.normpath(file), desc)
- if opts.verbosity:
- print msg
- errors.append(msg)
-
-null = file(os.path.devnull, "wb")
-
-# platform checking:
-iswindows = (sys.platform == "win32")
-
-# provide a (modified) copy of os.path.relpath from python 2.6
-def relpath(pathname, start=os.path.curdir):
- """Return a relative version of a path"""
-
- if not iswindows:
- pathname = os.path.expanduser(pathname)
- start_list = os.path.abspath(start).split(os.path.sep)
- path_list = os.path.abspath(pathname).split(os.path.sep)
-
- # Work out how much of the filepath is shared by start and path.
- i = len(os.path.commonprefix([start_list, path_list]))
-
- rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
- return os.path.join(*rel_list)
- else:
- start_list = os.path.abspath(start).split(os.path.sep)
- path_list = os.path.abspath(pathname).split(os.path.sep)
- if start_list[0].lower() != path_list[0].lower():
- unc_path, rest = os.path.splitunc(pathname)
- unc_start, rest = os.path.splitunc(start)
- if bool(unc_path) ^ bool(unc_start):
- raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
- % (pathname, start))
- else:
- raise ValueError("path is on drive %s, start on drive %s"
- % (path_list[0], start_list[0]))
- # Work out how much of the filepath is shared by start and path.
- for i in range(min(len(start_list), len(path_list))):
- if start_list[i].lower() != path_list[i].lower():
- break
- else:
- i += 1
-
- rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
- return os.path.join(*rel_list)
-
-def strippath(pathname, start):
- pathname = os.path.expanduser(pathname)
- pathname = os.path.abspath(os.path.join(start, pathname))
- start = os.path.abspath(start)
- if pathname[:len(start)] == start:
- return pathname[len(start)+1:]
- else:
- return pathname
-
-def alltexfiles(arglist):
- """iterate over all .tex files that are not ignored by -I"""
- for a in arglist:
- if os.path.isdir(a):
- for directory, subdirs, files in os.walk(a):
- if not opts.recurse:
- subdirs[:] = []
- else:
- for skipdir in (".svn", ".bzr"):
- if skipdir in subdirs:
- subdirs.remove(skipdir)
- for name in files:
- if re_texfile.match(name):
- if re_ignore.match(name):
- if opts.verbosity > 2:
- print "%s: skipped because of ignored name"%os.path.normpath(os.path.join(directory,name))
- else:
- yield (directory, name)
- elif os.path.exists(a):
- if re_texfile.match(a):
- (dirname, filename) = os.path.split(a)
- if dirname == "":
- dirname = "."
- yield (dirname, filename)
- else:
- error(a, "is no .tex file; skipped")
- elif os.path.exists(a+".tex"):
- (dirname, filename) = os.path.split(a+".tex")
- if dirname == "":
- dirname = "."
- yield(dirname, filename)
- else:
- error(a, "file not found")
-
-def needsupdate(dirname, texname, data=None):
- jobname = texname[:-4]
-
- if data == None:
- data = analyseTex(dirname, texname)
-
- # skip non-main files
- if not data.required:
- if opts.verbosity > 2:
- print "%s: skipped because no main latex file"%os.path.normpath(os.path.join(dirname,texname))
- return False
-
- # silent force
- if opts.force and not opts.verbosity:
- return True
-
- # check for nonexistant output file
- outname = jobname + ".pdf"
- outpath = os.path.join(dirname, outname)
- if not os.path.exists(outpath):
- return " (because .pdf does not exist)"
-
- # check for updated source and dependency files
- outdate = os.path.getmtime(outpath)
- if outdate < os.path.getmtime(os.path.join(dirname, texname)):
- return " (because .tex is newer than .pdf)"
- for deppath, extlist in data.deps:
- assert extlist == None
- if outdate < os.path.getmtime(os.path.join(dirname, deppath)):
- return " (because %s is newer than .pdf)"%deppath
-
- # check for errors and requests
- logname = jobname + ".log"
- if os.path.exists(os.path.join(dirname, logname)):
- logdata = analyseLog(dirname, jobname + ".log")
- if logdata.errors:
- return " (because of error(s) in .log file)"
- if logdata.requests:
- return " (because of request(s) in .log file)"
-
- # verbose force
- if opts.force:
- return " (because of --force)"
-
- # up to date
- if opts.verbosity > 2:
- print "%s: skipped because up-to-date"%os.path.normpath(os.path.join(dirname, texname))
- return False
-
-MAXRUNS=5
-def processTex(dirname, texname, data=None, reason=""):
- #strip .tex extension
- jobname=texname[:-4]
- jobpath = os.path.join(dirname,jobname)
- texpath = jobpath + ".tex"
- procfiles.append(os.path.normpath(texpath))
-
- if data == None:
- data = analyseTex(dirname, texname)
-
- if opts.verbosity:
- print "processing %s%s..."%(os.path.normpath(texpath),reason)
-
- # list of temporary files to be removed later
- tmplist = []
-
- # support for pstricks/plain latex:
- if data.needsPS:
- tex = "latex"
- else:
- tex = "pdflatex"
-
- # detect usage of german/ngerman and generate temporary files with rmlig
- realname = texname
-
- if data.rmligs:
- realname = preparermligs(texname, dirname, texpath, tmplist)
-
- # remove all outdated .bbl files (will be recreated by requests)
- bbls = bblfiles(dirname, jobname)
- for bib in data.bibfiles:
- bibpath = os.path.join(dirname, bib)
- bibtime = 0
- if os.path.exists(bibpath):
- bibtime = os.path.getmtime(bibpath)
- nextbbls = bbls[:]
- for bbl in bbls:
- bblpath = os.path.normpath(os.path.join(dirname, bbl))
- bbltime = os.path.getmtime(bblpath)
- if (opts.force and not opts.singlerun) or bbltime < bibtime:
- reason = ""
- if opts.verbosity:
- if bbltime < bibtime:
- reason = " (because %s is newer than %s)"%(bib,bbl)
- else:
- reason = " (because of --force)"
- rmtempfile(bblpath, force=True, reason=reason)
- nextbbls.remove(bbl)
- bbls = nextbbls
-
- runtex(tex, texname, realname, dirname)
-
- if not opts.singlerun:
- # check for undefined references and run requests
- numrun=0
- reqs=opts.act # ignore requests if programs are not run
- logname = jobname + ".log"
- while reqs:
- logdata = analyseLog(dirname, logname)
- reqs = logdata.requests
- for req in reqs:
- reason = ""
- if opts.verbosity:
- if req.reason:
- reason = req.reason
- else:
- reason = " (because of request in .log file, priority %d)"%req.priority
- if req.invocation:
- run(req.invocation, dirname, reason)
- elif req.progname == "latex":
- runtex(tex, texname, realname, dirname, reason=reason)
- elif req.progname == "bibtex":
- run( ("bibtex", jobname), dirname, reason)
- else:
- error(jobpath+".log", "unsupported request: %s"%req)
- numrun+=1
- if numrun==MAXRUNS:
- error(texpath, "does not stabilise after %i runs"%MAXRUNS)
- break
-
- # update index if it exists - no way of knowing if it was updated
- if os.path.exists(jobpath + ".idx"):
- run(["makeindex", jobname], dirname, reason=" (because .idx file might have changed)")
- runtex(tex, texname, realname, dirname, reason=" (because .ind file might have changed)")
-
- if data.needsPS:
- run(["dvips", jobname+".dvi"], dirname, stderr=subprocess.STDOUT)
- run(["ps2pdf", jobname+".ps"], dirname)
-
- rmtempfile(tmplist)
-
-def bblfiles(dirname, jobname):
- files = dircache.listdir(dirname)
- return fnmatch.filter(files, "%s*.bbl"%jobname)
-
-def rmtempfile(filenames, force=False, reason=""):
- if (opts.deletetempfiles or force) and filenames:
- if not isinstance(filenames, list):
- filenames = [filenames]
- if opts.verbosity > 1:
- print " removing %s%s"%(", ".join(filenames), reason)
- if opts.act:
- for f in filenames:
- if os.path.exists(f):
- os.remove(f)
- else:
- error(f, "could not be removed (does not exist)", warning=True)
-
-def run(arglist, dirname, reason="", inf=None, outf=None, stderr=None):
- """Run a command with optional io redirections.
-
- arglist -- list of progam name and arguments
- dirname -- the directory the command will be executed in
- reason -- reason for running this command, used in progress output
- inf -- file to be used as stdin, or alternativly a filter function for user input
- outf -- file to be used as stdout, or alternativly a filter function for program output
- stderr -- file to be used as stderr
- """
- if opts.verbosity:
- redir =""
- if hasattr(inf, "name") and inf.name != "" and inf.name[0] != "<":
- name = relpath(inf.name, dirname)
- redir = " < %s"%name
- print " running %s%s%s..."%(" ".join(arglist), redir, reason)
-
- if opts.act:
- master, slave = None, None
-
- if isinstance(inf, file):
- stdin = inf
- inf = None
- elif opts.showoutput and not iswindows:
- master, slave = pty.openpty()
- master = os.fdopen(master, "rw")
- stdin=slave
- elif inf or opts.showoutput:
- stdin=subprocess.PIPE
- else:
- stdin=null
-
- if isinstance(outf, file):
- stdout = outf
- outf = None
- elif opts.showoutput and not iswindows:
- if slave == None:
- master, slave = pty.openpty()
- master = os.fdopen(master, "rw")
- stdout=slave
- elif outf or opts.showoutput:
- stdout=subprocess.PIPE
- else:
- stdout=null
-
- try:
- proc = subprocess.Popen(arglist, stdin=stdin, stdout=stdout, stderr=stderr, cwd=dirname)
-
- if stdin == slave and stdin != None:
- childin = master
- else:
- childin = proc.stdin
- if stdout == slave and stdout != None:
- childout = master
- else:
- childout = proc.stdout
-
- selectlist = []
- outlist = []
- if childin != None:
- selectlist.append(sys.stdin)
- if childout != None:
- selectlist.append(childout)
- outlist.append(childout)
-
- while proc.poll() == None or select.select(outlist, [], [], 0)[0]:
- ready = select.select(selectlist, [], [], 0.1)[0]
- for f in ready:
- if f == childout:
- data = os.read(childout.fileno(), 1024)
- if data == "": # EOF
- outlist.remove(childout)
- selectlist.remove(childout)
- continue
- if outf: data = outf(data)
- if data != None:
- sys.stdout.write(data)
- sys.stdout.flush()
- if f == sys.stdin:
- if proc.poll() != None:
- # process terminated, does not take input anymore
- selectlist.remove(sys.stdin)
- continue
- data = os.read(sys.stdin.fileno(), 1024)
- if data == "": # EOF
- selectlist.remove(sys.stdin)
- continue
- if inf: data = inf(data)
- if data != None:
- childin.write(data)
- childin.flush()
- ret = proc.wait()
- if ret:
- error(dirname, "failed command: %s returned %i"%(" ".join(arglist), ret))
- except (OSError, IOError), e:
- error(dirname, "failed command: %s: %s"%(" ".join(arglist),str(e)))
-
-def runtex(tex, texname, realname, dirname, reason=""):
- if not opts.showoutput:
- outf = None
- else:
- def outf(d):
- d = re_fixemacserrorshowing.sub("", d)
- return re_rmligsfile.sub("\\1.tex", d)
- if texname != realname:
- run([tex, "-interaction", opts.interactionmode, "-jobname", texname[:-4], realname], dirname, outf=outf, reason=reason)
- else:
- run([tex, "-interaction", opts.interactionmode, texname], dirname, outf=outf, reason=reason)
-
-def preparermligs(texname, dirname, texpath, tmplist):
- try:
- texfile = open(texpath)
- except IOError, (errno, strerror):
- error(texpath, "could not be read: %s. Not using rmligs."%strerror)
- return texname
- else:
- try:
- (subdir, texbasename) = os.path.split(texname)
- rmligsbasename = "%s-rmligs.tex"%texbasename[:-4]
- rmligsname = os.path.join(subdir, rmligsbasename)
- rmligspath = os.path.join(dirname, rmligsname)
- if opts.act:
- rmligsfile = open(rmligspath, "w")
- else:
- rmligsfile = null
- except IOError, (errno, strerror):
- error(rmligspath, "could not be written: %s. Not using rmligs."%strerror)
- return texname
- else:
- tmplist.append(rmligspath)
- def rewriteinputrmligs(m):
- name = m.group(2)
- if not os.path.exists(os.path.join(dirname,name)):
- name+=".tex"
- path = os.path.join(dirname, name)
- if os.path.exists(path):
- name = preparermligs(name, dirname, path, tmplist)
- else:
- error(texpath, "%s: File could not be located. Not using rmligs."%name, warning=True)
- return "\\%s{%s}"%(m.group(1), name[:-4])
- def filteroutput(d):
- d = re_commentinclude.sub("", d)
- rmligsfile.write(re_inputinclude.sub(rewriteinputrmligs, d))
- return None
- run([rmligs_name, "-f"], dirname, inf=texfile, outf=filteroutput)
-
- texfile.close()
- if rmligsfile is not null:
- rmligsfile.close()
- return rmligsname
-
-# main program:
-def main(arguments):
- if not arguments:
- arguments = (".",)
-
- for dirname, texname in alltexfiles(arguments):
- data = analyseTex(dirname, texname)
- reason = needsupdate(dirname, texname, data)
- if reason:
- processTex(dirname, texname, data, reason)
-
-
- if opts.summary in [ "files", "both" ] :
- if procfiles:
- print "Processed the following files:"
- for f in procfiles:
- print " %s"%f
- else:
- print "Processed no files."
- if opts.summary in [ "failures", "both" ] :
- if errors:
- print "The following problems occured:"
- lasterr=""
- for f in errors:
- if f != lasterr:
- print " %s"%f
- lasterr = f
-
- if errors:
- sys.exit(1)
-
-try:
- if __name__ == "__main__":
- # setup global variables
- opts, programargs = TexallOptionParser().parse_args()
- else:
- opts, programargs = TexallOptionParser().parse_args([])
-
- re_ignore = None
- if opts.ignorepattern != "":
- re_ignore = re.compile(opts.ignorepattern)
-
- re_texfile = re.compile(".*\.tex$", re.I)
- if iswindows:
- re_systemfile = re.compile("^?:\\\\Program|\\.(sty|cls)$", re.I)
- re_nonlocal = re.compile("^?:\\\\")
- else:
- re_systemfile = re.compile("^/usr/|\\.(sty|cls)$")
- re_nonlocal = re.compile("^/")
-
- re_texcomment = re.compile("(?<!\\\\)%.*?$", re.M)
-
- re_required = re.compile(opts.requiredpattern, re.M)
-
- re_inputinclude = re.compile('\\\\(input|include|@input)\\{([^}]*)\\}')
- re_commentinclude = re.compile('(?<!\\\\)%[^%\n\r]*\\\\(input|include|@input)\\{([^}]*)\\}[^%\n\r]*?$', re.M)
- re_documentclass = re.compile('\\\\documentclass(\\[[^]]*\\])?\\{([^}]*)\\}')
- re_usepackage = re.compile('\\\\usepackage(\\[[^]]*\\])?\\{([^}]*)\\}')
- re_usetheme = re.compile('\\\\use(|color|font|inner|outer)theme(\\[[^]]*\\])?\\{([^}]*)\\}')
- re_graphics = re.compile('\\\\includegraphics(\\[[^]]*\\])?\\{([^}]*)\\}')
- re_DTLdep = re.compile('\\\\DTLload(rawdb|db)\\{[^}]*\\}\\{([^}]*)\\}')
-
- re_bibliography = re.compile('^[^%\n\r]*\\\\bibliography\\{([^}]*)\\}', re.M)
-
- re_commawhitespace = re.compile('\\s*,\\s*')
-
- re_needsps = re.compile('\\\\usepackage(\\[[^]]*\\])?\\{[^}]*pstricks[^}]*\\}')
- re_rmligs = re.compile('\\\usepackage((\\[[^]]*\\])?\\{n?german\\}|\\[[^]]*?german[^]]*\\]\\{babel\\})')
-
- re_logmatcher = re.compile("^LaTeX Warning: There were undefined references\.$|^LaTeX Warning: Label\(s\) may have changed\. Rerun to get cross-references right\.$|^REQ:(\d+):(\w+):REQ|^REQ:(\d+):(\w+):(.*?):REQ$|^No file [^\n]+\.bbl\.$", re.M | re.S)
- re_longreq = re.compile("^(binary|option|infile)=(.*?)$", re.M)
-
- re_error = re.compile('^! ', re.M)
- re_rmligsfile = re.compile("([^/ ]+)-rmligs\\.tex")
- re_fixemacserrorshowing = re.compile(" \(Web2C [0-9.]*\)")
-
- if __name__ == "__main__":
- #import cProfile
- #import pstats
- #cProfile.run("main(programargs)", "mystats")
- #p = pstats.Stats("mystats")
- #p.sort_stats('time').print_stats()
-
- main(programargs)
-
-except KeyboardInterrupt:
- sys.exit(2)
-else:
- for proc, master in kpseproc.values():
- os.close(master)
- os.kill(proc.pid, signal.SIGHUP)