1 """SCons.Scanner.LaTeX
2
3 This module implements the dependency scanner for LaTeX code.
4
5 """
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 __revision__ = "src/engine/SCons/Scanner/LaTeX.py 3363 2008/09/06 07:34:10 scons"
31
32 import os.path
33 import string
34
35 import SCons.Scanner
36
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 """
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
86
87 - def scan(self, node, path=()):
88
89
90
91
92
93
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
101
102
103
104
105
106 nodes = []
107 source_dir = node.get_dir()
108 for include in includes:
109
110
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