aboutsummaryrefslogtreecommitdiff
path: root/texall
diff options
context:
space:
mode:
Diffstat (limited to 'texall')
-rwxr-xr-xtexall273
1 files changed, 137 insertions, 136 deletions
diff --git a/texall b/texall
index 6a14ccc..afc2b37 100755
--- a/texall
+++ b/texall
@@ -11,58 +11,58 @@ import subprocess
import fnmatch
import dircache
-parser = OptionParser(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).")
-parser.add_option("-n", "--dry-run",
- action="store_false", dest="act", default=True,
- help="do not run any program")
-parser.add_option("-f", "--force",
- action="store_true", dest="force", default=False,
- help="regenerate up-to-date files")
-parser.add_option("-N", "--non-recursive",
- action="store_false", dest="recurse", default=True,
- help="disable recursion into subdirectories")
-parser.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")
-parser.add_option("-v", "--verbose",
- action="count", dest="verbosity", default=1,
- help="explain what is going on")
-parser.add_option("-q", "--quiet",
- action="store_const", dest="verbosity", const=0,
- help="suppress progress reports")
-parser.add_option("-o", "--show-output",
- action="store_true", dest="showoutput", default=False,
- help="show the output of the called programs")
-parser.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)")
-parser.add_option("-I", "--ignore",
- action="store", dest="ignorepattern", default=".*vorlage.*|\.\#.*|\..*\.rmligs\.tex",
- help="regular expression of filenames to ignore")
-parser.add_option("-P", "--required-pattern",
- action="store", dest="requiredpattern", default='^\\\\documentclass|%%% TeX-master: t',
- help="regular expression that must match the file content")
-parser.add_option("-T", "--preserve-tempfiles",
- action="store_false", dest="deletetempfiles", default=True,
- help="preserve temporary files (default: delete)")
-parser.add_option("-S", "--single-run",
- action="store_true", dest="singlerun", default=False,
- help="stop after the first LaTeX run, no matter if finished")
-(options, args) = parser.parse_args()
-
-if options.interactionmode == None:
- if options.showoutput:
- options.interactionmode = "nonstopmode"
+optparse = OptionParser(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).")
+optparse.add_option("-n", "--dry-run",
+ action="store_false", dest="act", default=True,
+ help="do not run any program")
+optparse.add_option("-f", "--force",
+ action="store_true", dest="force", default=False,
+ help="regenerate up-to-date files")
+optparse.add_option("-N", "--non-recursive",
+ action="store_false", dest="recurse", default=True,
+ help="disable recursion into subdirectories")
+optparse.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")
+optparse.add_option("-v", "--verbose",
+ action="count", dest="verbosity", default=1,
+ help="explain what is going on")
+optparse.add_option("-q", "--quiet",
+ action="store_const", dest="verbosity", const=0,
+ help="suppress progress reports")
+optparse.add_option("-o", "--show-output",
+ action="store_true", dest="showoutput", default=False,
+ help="show the output of the called programs")
+optparse.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)")
+optparse.add_option("-I", "--ignore",
+ action="store", dest="ignorepattern", default=".*vorlage.*|\.\#.*|\..*\.rmligs\.tex",
+ help="regular expression of filenames to ignore")
+optparse.add_option("-P", "--required-pattern",
+ action="store", dest="requiredpattern", default='^\\\\documentclass|%%% TeX-master: t',
+ help="regular expression that must match the file content")
+optparse.add_option("-T", "--preserve-tempfiles",
+ action="store_false", dest="deletetempfiles", default=True,
+ help="preserve temporary files (default: delete)")
+optparse.add_option("-S", "--single-run",
+ action="store_true", dest="singlerun", default=False,
+ help="stop after the first LaTeX run, no matter if finished")
+(opts, programargs) = optparse.parse_args()
+
+if opts.interactionmode == None:
+ if opts.showoutput:
+ opts.interactionmode = "nonstopmode"
else:
- options.interactionmode = "batchmode"
+ opts.interactionmode = "batchmode"
re_ignore = None
-if options.ignorepattern != "":
- re_ignore = re.compile(options.ignorepattern)
+if opts.ignorepattern != "":
+ re_ignore = re.compile(opts.ignorepattern)
-re_required = re.compile(options.requiredpattern)
+re_required = re.compile(opts.requiredpattern)
re_texfile = re.compile(".*\.tex$", re.I)
@@ -72,7 +72,7 @@ procfiles = []
errstr = {False: "ERROR", True: "WARNING"}
def error(file, desc, warning=False):
msg = "%s: %s: %s"%(errstr[warning], os.path.normpath(file), desc)
- if options.verbosity:
+ if opts.verbosity:
print msg
errors.append(msg)
@@ -82,30 +82,27 @@ null = file(os.path.devnull, "wb")
iswindows = (sys.platform == "win32")
# provide a copy of os.path.relpath from python 2.6
-if not iswindows:
- def relpath(path, start=os.path.curdir):
- """Return a relative version of a path"""
+def relpath(pathname, start=os.path.curdir):
+ """Return a relative version of a path"""
+ if not iswindows:
start_list = os.path.abspath(start).split(os.path.sep)
- path_list = os.path.abspath(path).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:
- def relpath(path, start=os.path.curdir):
- """Return a relative version of a path"""
-
+ else:
start_list = os.path.abspath(start).split(os.path.sep)
- path_list = os.path.abspath(path).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(path)
+ 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)"
- % (path, start))
+ % (pathname, start))
else:
raise ValueError("path is on drive %s, start on drive %s"
% (path_list[0], start_list[0]))
@@ -119,12 +116,12 @@ else:
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
return os.path.join(*rel_list)
-path = os.path.expandvars("$PATH")
-if path == "$PATH":
- path = os.path.defpath
-path = path.split(os.path.pathsep)
+binpath = os.path.expandvars("$PATH")
+if binpath == "$PATH":
+ binpath = os.path.defpath
+binpath = binpath.split(os.path.pathsep)
def isinpath(name):
- for p in path:
+ for p in binpath:
if os.path.isfile(os.path.join(p, name)):
return True
return False
@@ -138,24 +135,24 @@ else:
error("rmligs", "Command not found. Please install rmligs (or rmligs-german) for optimal results", warning=True)
# iterate over all .tex files that are not ignored by -i or -p
-def alltexfiles(args):
- for a in args:
+def alltexfiles(arglist):
+ for a in arglist:
if os.path.isdir(a):
- for dir, subdirs, files in os.walk(a):
- if not options.recurse:
+ for directory, subdirs, files in os.walk(a):
+ if not opts.recurse:
subdirs[:] = []
for name in files:
if re_texfile.match(name):
if re_ignore.match(name):
- if options.verbosity > 2:
- print "%s: skipped because of ignored name"%os.path.normpath(os.path.join(dir,name))
+ if opts.verbosity > 2:
+ print "%s: skipped because of ignored name"%os.path.normpath(os.path.join(directory,name))
continue
- for m in texgrep(re_required, dir, name):
- yield (dir, name)
+ for _ in texgrep(re_required, directory, name):
+ yield (directory, name)
break
else:
- if options.verbosity > 2:
- print "%s: skipped because no main latex file"%os.path.normpath(os.path.join(dir,name))
+ if opts.verbosity > 2:
+ print "%s: skipped because no main latex file"%os.path.normpath(os.path.join(directory,name))
elif os.path.isfile(a):
if re_texfile.match(a):
(dirname, filename) = os.path.split(a)
@@ -190,6 +187,7 @@ def texgrep(matcher, dirname, filename, recurse=False):
f.close()
kpsepaths={}
+#TODO: finish implementation, use in search
def texpath(dirname,filename,pathtype="tex",progname="latex",extlist=[],allowsystemfiles=False):
if not kpsepaths.has_key((pathtype,progname)):
kpse=subprocess.Popen(["kpsepath", "-n", progname, pathtype], stdout=subprocess.PIPE)
@@ -265,23 +263,23 @@ def bibfiles(dirname, texname):
if bib[-8:] != "-blx.bib":
yield bib
-def outdatedtexfiles(args):
- for dirname, texname in alltexfiles(args):
+def outdatedtexfiles(arglist):
+ for dirname, texname in alltexfiles(arglist):
#strip .tex extension
jobname=texname[:-4]
pdfname=jobname+".pdf"
reason = ""
# check if an update is needed:
- if options.force and not options.verbosity:
+ if opts.force and not opts.verbosity:
yield (dirname, texname, reason)
elif not os.path.isfile(os.path.join(dirname,pdfname)):
- if options.verbosity:
+ if opts.verbosity:
reason = " (because .pdf does not exist)"
yield (dirname, texname, reason)
else:
pdftime = os.path.getmtime(os.path.join(dirname, pdfname))
if pdftime < os.path.getmtime(os.path.join(dirname, texname)):
- if options.verbosity:
+ if opts.verbosity:
reason = " (because .tex is newer than .pdf)"
yield (dirname, texname, reason)
else:
@@ -290,25 +288,25 @@ def outdatedtexfiles(args):
error(os.path.join(dirname,texname), "dependency not found: %s"%f, warning=True)
continue
if pdftime < os.path.getmtime(f):
- if options.verbosity:
+ if opts.verbosity:
reason = " (because %s is newer than .pdf)"%f
yield (dirname, texname, reason)
break
else:
r = haderrors(dirname, jobname)
if r:
- if options.verbosity:
+ if opts.verbosity:
reason = r
yield (dirname, texname, reason)
- elif options.force:
+ elif opts.force:
reason = " (because of --force)"
yield (dirname, texname, reason)
- elif options.verbosity > 2:
+ elif opts.verbosity > 2:
print "%s: skipped because up-to-date"%os.path.normpath(os.path.join(dirname, texname))
re_nopdftex = re.compile('\\\\usepackage(\\[.*?\\])?\\{[^}]*pstricks[^}]*\\}')
def detecttextype(dirname, texname):
- for m in texgrep(re_nopdftex, dirname, texname, recurse=True):
+ for _ in texgrep(re_nopdftex, dirname, texname, recurse=True):
return "latex"
return "pdflatex"
@@ -316,7 +314,7 @@ re_rmligs = re.compile('\\\usepackage((\\[.*?\\])?\\{n?german\\}|\\[[^]]*?german
def detectrmligs(dirname, texname):
if rmligs_name == "":
return False
- for m in texgrep(re_rmligs, dirname, texname, recurse=True):
+ for _ in texgrep(re_rmligs, dirname, texname, recurse=True):
return True
return False
@@ -325,10 +323,10 @@ def bblfiles(dirname, jobname):
return fnmatch.filter(files, "%s*.bbl"%jobname)
MAXRUNS=5
-def processtexfiles(args):
- for dirname, texname, reason in outdatedtexfiles(args):
+def processtexfiles(arglist):
+ for dirname, texname, reason in outdatedtexfiles(arglist):
procfiles.append(os.path.normpath(os.path.join(dirname,texname)))
- if options.verbosity:
+ if opts.verbosity:
print "processing %s%s..."%(os.path.normpath(os.path.join(dirname,texname)),reason)
# list of temporary files to be removed later
@@ -347,7 +345,6 @@ def processtexfiles(args):
# remove all outdated .bbl files (will be recreated by requests)
bbls = bblfiles(dirname, jobname)
- bblname = jobname+".bbl"
for bib in bibfiles(dirname, texname):
bibpath = os.path.join(dirname, os.path.expanduser(bib))
bibtime = os.path.getmtime(bibpath)
@@ -355,9 +352,9 @@ def processtexfiles(args):
for bbl in bbls:
bblpath = os.path.normpath(os.path.join(dirname, bbl))
bbltime = os.path.getmtime(bblpath)
- if (options.force and not options.singlerun) or bbltime < bibtime:
+ if (opts.force and not opts.singlerun) or bbltime < bibtime:
reason = ""
- if options.verbosity:
+ if opts.verbosity:
if bbltime < bibtime:
reason = " (because %s is newer than %s)"%(bib,bbl)
else:
@@ -368,10 +365,10 @@ def processtexfiles(args):
runtex(tex, texname, realname, dirname)
- if not options.singlerun:
+ if not opts.singlerun:
# check for undefined references and run requests
numrun=0
- reqs=options.act
+ reqs=opts.act
while reqs:
reqs = requests(os.path.join(dirname, jobname+".log"))
if not reqs: break
@@ -385,7 +382,7 @@ def processtexfiles(args):
rp = reqs[req]
if rp == p:
reason = ""
- if options.verbosity:
+ if opts.verbosity:
reason = " (because of request in .aux file, priority %d)"%rp
if req == "latex":
runtex(tex, texname, realname, dirname, reason=reason)
@@ -421,6 +418,8 @@ def requests(logpath):
try:
log = open(logpath)
inrequest = False
+ reqpri = None
+ reqoptions = []
for line in log:
if inrequest:
# strip newline character
@@ -459,7 +458,6 @@ def requests(logpath):
addrequest(m.group(2), int(m.group(1)))
elif m.group(3)!=None:
inrequest = True
- reqname = m.group(4)
reqpri = int(m.group(3))
reqbinary = None
reqoptions = []
@@ -488,14 +486,14 @@ def haderrors(dirname, jobname):
f.close()
return False
-def rmtempfile(filename, dirname, force=False, reason=""):
- if options.deletetempfiles:
- if not isinstance(filename, list):
- filename = [filename]
- if options.verbosity > 1:
- print " removing %s%s"%(", ".join(filename), reason)
- if options.act:
- for f in filename:
+def rmtempfile(filenames, dirname, force=False, reason=""):
+ if opts.deletetempfiles or force:
+ 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:
fullname = os.path.join(dirname, f)
if os.path.isfile(fullname):
os.remove(fullname)
@@ -512,24 +510,24 @@ def run(arglist, dirname, reason="", inf=None, outf=None, stderr=None):
outf -- file to be used as stdout, or alternativly a filter function for program output
stderr -- file to be used as stderr
"""
- if options.verbosity:
+ 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 options.act:
+ if opts.act:
master, slave = None, None
if isinstance(inf, file):
stdin = inf
inf = None
- elif options.showoutput and not iswindows:
+ elif opts.showoutput and not iswindows:
master, slave = pty.openpty()
master = os.fdopen(master, "rw")
stdin=slave
- elif inf or options.showoutput:
+ elif inf or opts.showoutput:
stdin=subprocess.PIPE
else:
stdin=null
@@ -537,12 +535,12 @@ def run(arglist, dirname, reason="", inf=None, outf=None, stderr=None):
if isinstance(outf, file):
stdout = outf
outf = None
- elif options.showoutput and not iswindows:
+ elif opts.showoutput and not iswindows:
if slave == None:
master, slave = pty.openpty()
master = os.fdopen(master, "rw")
stdout=slave
- elif outf or options.showoutput:
+ elif outf or opts.showoutput:
stdout=subprocess.PIPE
else:
stdout=null
@@ -600,7 +598,6 @@ def run(arglist, dirname, reason="", inf=None, outf=None, stderr=None):
error(dirname, "failed command: %s: %s"%(" ".join(arglist),str(e)))
def preparermligs(texname, dirname, tmplist):
- jobname=texname[:-4]
try:
texfile = open(os.path.join(dirname, texname))
except IOError, (errno, strerror):
@@ -611,7 +608,7 @@ def preparermligs(texname, dirname, tmplist):
(subdir, texbasename) = os.path.split(texname)
rmligsbasename = ".%s.rmligs.tex"%texbasename[:-4]
rmligsname = os.path.join(subdir, rmligsbasename)
- if options.act:
+ if opts.act:
rmligsfile = open(os.path.join(dirname, rmligsname), "w")
else:
rmligsfile = null
@@ -628,7 +625,7 @@ def preparermligs(texname, dirname, tmplist):
if os.path.isfile(os.path.join(dirname, name)):
name = preparermligs(name, dirname, tmplist)
else:
- error(os.path.join(dirnam, texname), "%s: File could not be located. Not using rmligs."%name, warning=True)
+ error(os.path.join(dirname, texname), "%s: File could not be located. Not using rmligs."%name, warning=True)
return "\\%s{%s}"%(m.group(1), name[:-4])
def filteroutput(d):
rmligsfile.write(re_inputinclude.sub(rewriteinputrmligs, d))
@@ -642,38 +639,42 @@ def preparermligs(texname, dirname, tmplist):
re_rmligsfile = re.compile("\\.([^/ ]+)\\.rmligs\\.tex")
def runtex(tex, texname, realname, dirname, reason=""):
- if not options.showoutput:
+ if not opts.showoutput:
outf = None
else:
def outf(d):
return re_rmligsfile.sub("\\1.tex", d)
if texname != realname:
- run([tex, "-interaction", options.interactionmode, "-jobname", texname[:-4], realname], dirname, outf=outf, reason=reason)
+ run([tex, "-interaction", opts.interactionmode, "-jobname", texname[:-4], realname], dirname, outf=outf, reason=reason)
else:
- run([tex, "-interaction", options.interactionmode, texname], dirname, outf=outf, reason=reason)
+ run([tex, "-interaction", opts.interactionmode, texname], dirname, outf=outf, reason=reason)
# main program:
-try:
- if args:
- processtexfiles(args)
- else:
- processtexfiles(["."])
-
- if options.summary in [ "files", "both" ] :
- if procfiles:
- print "Processed the following files:"
- for f in procfiles:
- print " %s"%f
+def main():
+ try:
+ if programargs:
+ processtexfiles(programargs)
else:
- print "Processed no files."
- if options.summary in [ "failures", "both" ] :
+ processtexfiles(["."])
+
+ 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:"
+ for f in errors:
+ print " %s"%f
+
if errors:
- print "The following problems occured:"
- for f in errors:
- print " %s"%f
+ sys.exit(1)
- if errors:
- sys.exit(1)
+ except KeyboardInterrupt:
+ sys.exit(2)
-except KeyboardInterrupt:
- sys.exit(2)
+if __name__ == "__main__":
+ main()