aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Kuhnert2008-08-25 08:52:47 +0000
committerSebastian Kuhnert2008-08-25 08:52:47 +0000
commit37b5728aca04d2aa94f285ce9a25aff7c2308cd4 (patch)
treeffed0e98a6a6cd50ff623e4d862c2a48a571765e
parentd5df1ecdbddae821388210af19177e6e1489410d (diff)
downloadexercisesheets-37b5728aca04d2aa94f285ce9a25aff7c2308cd4.tar.gz
exercisesheets-37b5728aca04d2aa94f285ce9a25aff7c2308cd4.tar.bz2
exercisesheets-37b5728aca04d2aa94f285ce9a25aff7c2308cd4.zip
texall script: finish pty support
-rwxr-xr-xtexall152
1 files changed, 114 insertions, 38 deletions
diff --git a/texall b/texall
index dcefe73..82516ce 100755
--- a/texall
+++ b/texall
@@ -4,7 +4,9 @@ from optparse import OptionParser
import sys
import os
import os.path
+import pty
import re
+import select
import subprocess
parser = OptionParser(usage="%prog [options] DIR/FILE",
@@ -28,9 +30,12 @@ parser.add_option("-v", "--verbose",
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"), default="batchmode",
- help="control the behaviour of latex (on of batchmode (default), nonstopmode, scrollmode, errorstopmode)")
+ 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.*|\.\#.*",
help="regular expression of filenames to ignore")
@@ -45,6 +50,12 @@ parser.add_option("-S", "--single-run",
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"
+ else:
+ options.interactionmode = "batchmode"
+
re_ignore = None
if options.ignorepattern != "":
re_ignore = re.compile(options.ignorepattern)
@@ -404,28 +415,98 @@ def rmtempfile(filename, dirname):
else:
error(fullname, "could not be removed (does not exist)", warning=True)
-def run(arglist, dirname, reason="", stdin=None, stdout=None, stderr=None, doio=None):
- if options.interactionmode == "batchmode":
- if not stdout:
- stdout=null
- if not stderr:
- stderr=null
+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 options.verbosity:
- redir = ""
- if hasattr(stdin, "name"):
- redir = "%s < %s"%(redir, stdin.name)
- if hasattr(stdout, "name") and stdout is not null:
- redir = "%s > %s"%(redir, stdout.name)
- if hasattr(stderr, "name") and stderr is not null:
- redir = "%s 2> %s"%(redir, stderr.name)
- print " running %s%s%s..."%(" ".join(arglist), redir, reason)
+ print " running %s%s..."%(" ".join(arglist), reason)
+
if options.act:
- proc = subprocess.Popen(arglist, stdin=stdin, stdout=stdout, stderr=stderr, cwd=dirname)
- if doio:
- doio(proc)
- ret = proc.wait()
- if ret:
- error(dirname, "failed command: %s"%(" ".join(arglist)))
+ master, slave = None, None
+
+ if isinstance(inf, file):
+ stdin = inf
+ inf = None
+ elif options.showoutput and not subprocess.mswindows:
+ master, slave = pty.openpty()
+ master = os.fdopen(master, "rw")
+ stdin=slave
+ elif inf or options.showoutput:
+ stdin=subprocess.PIPE
+ else:
+ stdin=null
+
+ if isinstance(outf, file):
+ stdout = outf
+ outf = None
+ elif options.showoutput and not subprocess.mswindows:
+ if slave == None:
+ master, slave = pty.openpty()
+ master = os.fdopen(master, "rw")
+ stdout=slave
+ elif outf or options.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 preparermligs(texname, dirname, tmplist):
jobname=texname[:-4]
@@ -458,10 +539,10 @@ def preparermligs(texname, dirname, tmplist):
else:
error(os.path.join(dirnam, texname), "%s: File could not be located. Not using rmligs."%name, warning=True)
return "\\%s{%s}"%(m.group(1), name[:-4])
- def doio(p):
- for line in p.stdout:
- rmligsfile.write(re_inputinclude.sub(rewriteinputrmligs, line))
- run([rmligs_name, "-f"], dirname, stdin=texfile, stdout=subprocess.PIPE, doio=doio)
+ def filteroutput(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:
@@ -469,21 +550,16 @@ def preparermligs(texname, dirname, tmplist):
return rmligsname
re_rmligsfile = re.compile("\\.([^/ ]+)\\.rmligs\\.tex")
-def rmligscleanoutput(p): # filter tex output to make emacs jump to the right source positions
- for l in p.stdout:
- sys.stdout.write(re_rmligsfile.sub("\\1.tex", l))
- sys.stdout.flush()
def runtex(tex, texname, realname, dirname, reason=""):
+ if not options.showoutput:
+ outf = None
+ else:
+ def outf(d):
+ return re_rmligsfile.sub("\\1.tex", d)
if texname != realname:
- if options.interactionmode == "batchmode":
- stdout = None
- doio = None
- else:
- stdout = subprocess.PIPE
- doio = rmligscleanoutput
- run([tex, "-interaction", options.interactionmode, "-jobname", texname[:-4], realname], dirname, stdout=stdout, doio=doio, reason=reason)
+ run([tex, "-interaction", options.interactionmode, "-jobname", texname[:-4], realname], dirname, outf=outf, reason=reason)
else:
- run([tex, "-interaction", options.interactionmode, texname], dirname, reason=reason)
+ run([tex, "-interaction", options.interactionmode, texname], dirname, outf=outf, reason=reason)
# main program:
try: