Guest User

latexfilter.py

a guest
May 31st, 2017
398
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.91 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import sys
  4. import getopt
  5. import re
  6. import string
  7.  
  8. wrap = 79
  9. debug = False
  10. verbose = False
  11. quiet = False
  12.  
  13. def usage(argv0):
  14.   print >> sys.stderr, """
  15. usage: %s [options]
  16. options:
  17.  -h,-?,--help   : print this message
  18.  -q,-quiet      : suppress even more TeX and LaTeX output
  19.  -v,-verbose    : allow all TeX and LaTeX output
  20.  -d,-debug      : debug this script
  21. """ % (argv0)
  22.  
  23. def msg(s):
  24.   global debug, lineno
  25.   if debug:
  26.     #print >>sys.stderr, s
  27.     print ("[input line %d] " % lineno) + s
  28.  
  29. lineno = 0
  30.  
  31. def read_partial_line():
  32.   global lineno
  33.   line = sys.stdin.readline()
  34.   if not line:
  35.     return None
  36.   lineno += 1
  37.   return line[:-1] if line.endswith('\n') else line
  38.  
  39. def read_line_unwrapped():
  40.   global verbatim_next_line
  41.   line = read_partial_line()
  42.   if verbatim_next_line:
  43.     return line
  44.   if line is None:
  45.     return None
  46.   n = len(line)
  47.   while n == wrap:
  48.     cont = read_partial_line()
  49.     line += cont
  50.     n = len(cont)
  51.   return line
  52.  
  53. re_fatal = re.compile(".*==> Fatal error")
  54. # re_error = re.compile("^l\.[1-9]\d* |^\.?/.*:[1-9]\d*: ")
  55. re_error = re.compile("^l\.[1-9]\d* |^<argument> ")
  56. # re_error = re.compile("^l\.[1-9]\d* ")
  57.  
  58. re_underfull = re.compile("Underfull ")
  59. re_overfull = re.compile("Overfull ")
  60.  
  61. re_xparse = re.compile("\* LaTeX warning: \"xparse/redefine-command\"$")
  62.  
  63.  
  64. re_ignore = re.compile(string.join( [
  65.   "entering extended mode$",
  66.   "LaTeX2e <.*>$",
  67.   "Package: `setspace' [\d\.]* <.*>$",
  68.   "Package scrlfile, .* \(loading files\)$",
  69.   "For additional information .*$",
  70.   "Copyright \(C\) Markus Kohm",
  71.   "\*{49}$",
  72.   "Babel.*loaded\.$",
  73.   "\[Loading MPS to PDF converter.*\]$",
  74.   "LaTeX Warning: Marginpar on page \d* moved\.$",
  75.   "{[^ ]*}",
  76.   "{\"?C:[/\\\\][^\"]*\"?}",
  77.   "Non-PDF special ignored!",
  78.   "No file .*\.bbl\.$",
  79.   "LaTeX Warning: There were undefined references\.$",
  80.   "\(see the transcript file for additional information\)",
  81.   "{C:/Program Files/MiKTeX.*}<.*>$",
  82.   "<[^>]*/[^>]*>"
  83.   ], "|"))
  84.  
  85. re_reference = re.compile("LaTeX Warning: Reference ")
  86. re_citation = re.compile("LaTeX Warning: Citation `.*' on page \d* undefined on input line \d*\.")
  87.  
  88.  
  89. re_fileref = re.compile('\([\.]*/|\("?C:[/\\\\]')
  90.  
  91. def lstrip_filename(s):
  92.   if len(s) > 2 and s[0] == '"':
  93.     i = s.find('"', 1)
  94.     if i == len(s)-1:
  95.       return (s, None)
  96.     else:
  97.       return (s[:i], s[i+1:])
  98.   for i in range(0, len(s)):
  99.     if s[i] == ')':
  100.       return (s[:i], s[i:])
  101.     elif s[i] == ' ':
  102.       return (s[:i], s[i+1:])
  103.   return (s, None)
  104.  
  105. def lstrip_pageno(s):
  106.   for i in range(0, len(s)):
  107.     if s[i] < '0' or s[i] > '9':
  108.       return (s[:i], s[i:])
  109.   return (s, None)
  110.  
  111. parens = 0
  112. inpage = False
  113. underfull = 0
  114. overfull = 0
  115. references = 0
  116. citations = 0
  117. ignore_next_lines = 0
  118. verbatim_next_line = False
  119. status = 0
  120.  
  121. last_match = None
  122. def save(m):
  123.   global last_match
  124.   last_match = m
  125.   return m
  126.  
  127. def filter(line):
  128.   global parens, inpage, ignore_next_lines, verbatim_next_line, underfull, overfull, references, citations, status
  129.  
  130.   if ignore_next_lines > 0:
  131.     ignore_next_lines = ignore_next_lines - 1
  132.     return None
  133.  
  134.   if verbatim_next_line:
  135.     verbatim_next_line = False
  136.     print line
  137.     return None
  138.  
  139.   # msg("filter: %s" % line)
  140.   originalline = line
  141.   line = line.lstrip()
  142.   if not line:
  143.     return None
  144.   elif save(re_ignore.match(line)):
  145.     # msg("..." + line)
  146.     return line[last_match.end():]
  147.   elif re_fileref.match(line):
  148.     parens += 1
  149.     # read a file name (assuming no spaces in file names) and keep filtering
  150.     (filename,line) = lstrip_filename(line[1:])
  151.     # msg("...processing file: %s" % (filename))
  152.     return line
  153.   elif line[0] == ')':
  154.     if parens == 0:
  155.       msg("mismatched right paren")
  156.     else:
  157.       parens -= 1
  158.     return line[1:]
  159.   elif line[0] == '[' and line[1] in ('1', '2', '3', '4', '5', '6', '7', '8', '9'):
  160.     if inpage:
  161.       msg("starting new page, but didn't finish last one")
  162.     inpage = True
  163.     (pageno, line) = lstrip_pageno(line[1:])
  164.     # msg("... processing page: %s" % pageno)
  165.     return line
  166.   elif line[0] == ']':
  167.     if not inpage:
  168.       msg("endingn page, but never started one")
  169.     inpage = False
  170.     return line[1:]
  171.   elif re_xparse.match(line):
  172.     ignore_next_lines = 2
  173.     return None
  174.   elif re_underfull.match(line):
  175.     underfull += 1
  176.     ignore_next_lines = 1
  177.     return None
  178.   elif re_overfull.match(line):
  179.     overfull += 1
  180.     ignore_next_lines = 1
  181.     return None
  182.   elif re_reference.match(line):
  183.     references += 1
  184.     if not quiet:
  185.       print originalline
  186.     return None
  187.   elif re_citation.match(line):
  188.     citations += 1
  189.     if not quiet:
  190.       print originalline
  191.     return None
  192.   elif re_fatal.match(line):
  193.     print originalline
  194.     status = 1
  195.     return None
  196.   elif re_error.match(line):
  197.     print originalline
  198.     verbatim_next_line = 1
  199.     return None
  200.   else:
  201.     print originalline
  202.     return None
  203.  
  204. def main(argv):
  205.   global debug, verbose, quiet, wrap
  206.  
  207.   try:
  208.     opts, args = getopt.getopt(argv[1:], "h?dvq", ["help", "quiet", "verbose", "debug"])
  209.   except getopt.GetoptError:
  210.     usage(argv[0])
  211.     sys.exit(2)
  212.   for opt, arg in opts:
  213.     if opt in ("-h", "-?", "--help"):
  214.       usage(argv[0])
  215.       sys.exit()
  216.     elif opt in ('-d', '--debug'):
  217.       debug = True
  218.     elif opt in ('-q', '--quiet'):
  219.       quiet = True
  220.     elif opt in ('-v', '--verbose'):
  221.       verbose = True
  222.   if quiet and verbose:
  223.     quiet = False
  224.  
  225.   while True:
  226.     line = read_line_unwrapped()
  227.     if line is None:
  228.       break
  229.     while not (line is None):
  230.       line = filter(line)
  231.  
  232.   if status:
  233.     sys.exit(status)
  234.  
  235.   print "Number of underfull warnings   : %d" % underfull
  236.   print "Number of overfull warnings    : %d" % overfull
  237.   print "Number of undefined references : %d" % references
  238.   print "Number of missing citations    : %d" % citations
  239.  
  240. if __name__ == "__main__":
  241.   main(sys.argv)
Advertisement
Add Comment
Please, Sign In to add comment