Package SCons :: Package Scanner :: Module LaTeX
[hide private]
[frames] | no frames]

Source Code for Module SCons.Scanner.LaTeX

  1  """SCons.Scanner.LaTeX 
  2   
  3  This module implements the dependency scanner for LaTeX code. 
  4   
  5  """ 
  6   
  7  # 
  8  # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation 
  9  # 
 10  # Permission is hereby granted, free of charge, to any person obtaining 
 11  # a copy of this software and associated documentation files (the 
 12  # "Software"), to deal in the Software without restriction, including 
 13  # without limitation the rights to use, copy, modify, merge, publish, 
 14  # distribute, sublicense, and/or sell copies of the Software, and to 
 15  # permit persons to whom the Software is furnished to do so, subject to 
 16  # the following conditions: 
 17  # 
 18  # The above copyright notice and this permission notice shall be included 
 19  # in all copies or substantial portions of the Software. 
 20  # 
 21  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 22  # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 23  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 24  # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
 25  # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
 26  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
 27  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 28  # 
 29   
 30  __revision__ = "src/engine/SCons/Scanner/LaTeX.py 3266 2008/08/12 07:31:01 knight" 
 31   
 32  import os.path 
 33  import string 
 34   
 35  import SCons.Scanner 
 36   
37 -def LaTeXScanner():
38 """Return a prototype Scanner instance for scanning LaTeX source files""" 39 ds = LaTeX(name = "LaTeXScanner", 40 suffixes = '$LATEXSUFFIXES', 41 path_variable = 'TEXINPUTS', 42 regex = '\\\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography|usepackage){([^}]*)}', 43 recursive = 0) 44 return ds
45
46 -class LaTeX(SCons.Scanner.Classic):
47 """Class for scanning LaTeX files for included files. 48 49 Unlike most scanners, which use regular expressions that just 50 return the included file name, this returns a tuple consisting 51 of the keyword for the inclusion ("include", "includegraphics", 52 "input", or "bibliography"), and then the file name itself. 53 Based on a quick look at LaTeX documentation, it seems that we 54 need a should append .tex suffix for the "include" keywords, 55 append .tex if there is no extension for the "input" keyword, 56 but leave the file name untouched for "includegraphics." For 57 the "bibliography" keyword we need to add .bib if there is 58 no extension. (This need to be revisited since if there 59 is no extension for an "includegraphics" keyword latex will 60 append .ps or .eps to find the file; while pdftex will use 61 other extensions.) 62 """
63 - def latex_name(self, include):
64 filename = include[1] 65 if include[0] == 'input': 66 base, ext = os.path.splitext( filename ) 67 if ext == "": 68 filename = filename + '.tex' 69 if (include[0] == 'include'): 70 filename = filename + '.tex' 71 if include[0] == 'bibliography': 72 base, ext = os.path.splitext( filename ) 73 if ext == "": 74 filename = filename + '.bib' 75 if include[0] == 'usepackage': 76 base, ext = os.path.splitext( filename ) 77 if ext == "": 78 filename = filename + '.sty' 79 return filename
80 - def sort_key(self, include):
81 return SCons.Node.FS._my_normcase(self.latex_name(include))
82 - def find_include(self, include, source_dir, path):
83 i = SCons.Node.FS.find_file(self.latex_name(include), 84 (source_dir,) + path) 85 return i, include
86
87 - def scan(self, node, path=()):
88 # 89 # Modify the default scan function to allow for the regular 90 # expression to return a comma separated list of file names 91 # as can be the case with the bibliography keyword. 92 # 93 # cache the includes list in node so we only scan it once: 94 if node.includes != None: 95 includes = node.includes 96 else: 97 includes = self.cre.findall(node.get_contents()) 98 node.includes = includes 99 100 # This is a hand-coded DSU (decorate-sort-undecorate, or 101 # Schwartzian transform) pattern. The sort key is the raw name 102 # of the file as specifed on the #include line (including the 103 # " or <, since that may affect what file is found), which lets 104 # us keep the sort order constant regardless of whether the file 105 # is actually found in a Repository or locally. 106 nodes = [] 107 source_dir = node.get_dir() 108 for include in includes: 109 # 110 # Handle multiple filenames in include[1] 111 # 112 inc_list = string.split(include[1],',') 113 for j in range(len(inc_list)): 114 include_local = [include[0],inc_list[j]] 115 n, i = self.find_include(include_local, source_dir, path) 116 117 if n is None: 118 SCons.Warnings.warn(SCons.Warnings.DependencyWarning, 119 "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) 120 else: 121 sortkey = self.sort_key(include) 122 nodes.append((sortkey, n)) 123 124 nodes.sort() 125 nodes = map(lambda pair: pair[1], nodes) 126 return nodes
127