SCons.Scanner.LaTeX

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 2725 2008/03/31 12:52:02 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