summaryrefslogtreecommitdiff
path: root/engine/SCons/Scanner/LaTeX.py
diff options
context:
space:
mode:
Diffstat (limited to 'engine/SCons/Scanner/LaTeX.py')
-rw-r--r--engine/SCons/Scanner/LaTeX.py129
1 files changed, 88 insertions, 41 deletions
diff --git a/engine/SCons/Scanner/LaTeX.py b/engine/SCons/Scanner/LaTeX.py
index 0a68b7e..69154bd 100644
--- a/engine/SCons/Scanner/LaTeX.py
+++ b/engine/SCons/Scanner/LaTeX.py
@@ -5,7 +5,7 @@ This module implements the dependency scanner for LaTeX code.
"""
#
-# Copyright (c) 2001 - 2016 The SCons Foundation
+# Copyright (c) 2001 - 2017 The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -27,7 +27,7 @@ This module implements the dependency scanner for LaTeX code.
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog"
+__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
import os.path
import re
@@ -37,7 +37,9 @@ import SCons.Util
# list of graphics file extensions for TeX and LaTeX
TexGraphics = ['.eps', '.ps']
-LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif']
+#LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif']
+LatexGraphics = [ '.png', '.jpg', '.gif', '.tif']
+
# Used as a return value of modify_env_var if the variable is not set.
class _Null(object):
@@ -76,8 +78,10 @@ def modify_env_var(env, var, abspath):
return save
class FindENVPathDirs(object):
- """A class to bind a specific *PATH variable name to a function that
- will return all of the *path directories."""
+ """
+ A class to bind a specific E{*}PATH variable name to a function that
+ will return all of the E{*}path directories.
+ """
def __init__(self, variable):
self.variable = variable
def __call__(self, env, dir=None, target=None, source=None, argument=None):
@@ -94,7 +98,8 @@ class FindENVPathDirs(object):
def LaTeXScanner():
- """Return a prototype Scanner instance for scanning LaTeX source files
+ """
+ Return a prototype Scanner instance for scanning LaTeX source files
when built with latex.
"""
ds = LaTeX(name = "LaTeXScanner",
@@ -105,7 +110,8 @@ def LaTeXScanner():
return ds
def PDFLaTeXScanner():
- """Return a prototype Scanner instance for scanning LaTeX source files
+ """
+ Return a prototype Scanner instance for scanning LaTeX source files
when built with pdflatex.
"""
ds = LaTeX(name = "PDFLaTeXScanner",
@@ -116,7 +122,8 @@ def PDFLaTeXScanner():
return ds
class LaTeX(SCons.Scanner.Base):
- """Class for scanning LaTeX files for included files.
+ """
+ Class for scanning LaTeX files for included files.
Unlike most scanners, which use regular expressions that just
return the included file name, this returns a tuple consisting
@@ -133,10 +140,12 @@ class LaTeX(SCons.Scanner.Base):
The actual subset and search order may be altered by
DeclareGraphicsExtensions command. This complication is ignored.
- The default order corresponds to experimentation with teTeX
+ The default order corresponds to experimentation with teTeX::
+
$ latex --version
pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4)
kpathsea version 3.5.4
+
The order is:
['.eps', '.ps'] for latex
['.png', '.pdf', '.jpg', '.tif'].
@@ -148,8 +157,7 @@ class LaTeX(SCons.Scanner.Base):
env['TEXINPUTS'] for "lstinputlisting" keyword
env['BIBINPUTS'] for "bibliography" keyword
env['BSTINPUTS'] for "bibliographystyle" keyword
- env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed
- just allows user to set it if needed.
+ env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed just allows user to set it if needed.
FIXME: also look for the class or style in document[class|style]{}
FIXME: also look for the argument of bibliographystyle{}
@@ -166,6 +174,9 @@ class LaTeX(SCons.Scanner.Base):
'usepackage': 'TEXINPUTS',
'lstinputlisting': 'TEXINPUTS'}
env_variables = SCons.Util.unique(list(keyword_paths.values()))
+ two_arg_commands = ['import', 'subimport',
+ 'includefrom', 'subincludefrom',
+ 'inputfrom', 'subinputfrom']
def __init__(self, name, suffixes, graphics_extensions, *args, **kw):
@@ -175,8 +186,29 @@ class LaTeX(SCons.Scanner.Base):
# line followed by one or more newline characters (i.e. blank
# lines), interfering with a match on the next line.
# add option for whitespace before the '[options]' or the '{filename}'
- regex = r'^[^%\n]*\\(include|includegraphics(?:\s*\[[^\]]+\])?|lstinputlisting(?:\[[^\]]+\])?|input|bibliography|addbibresource|addglobalbib|addsectionbib|usepackage)\s*{([^}]*)}'
- self.cre = re.compile(regex, re.M)
+ regex = r'''
+ ^[^%\n]*
+ \\(
+ include
+ | includegraphics(?:\s*\[[^\]]+\])?
+ | lstinputlisting(?:\[[^\]]+\])?
+ | input
+ | import
+ | subimport
+ | includefrom
+ | subincludefrom
+ | inputfrom
+ | subinputfrom
+ | bibliography
+ | addbibresource
+ | addglobalbib
+ | addsectionbib
+ | usepackage
+ )
+ \s*{([^}]*)} # first arg
+ (?: \s*{([^}]*)} )? # maybe another arg
+ '''
+ self.cre = re.compile(regex, re.M | re.X)
self.comment_re = re.compile(r'^((?:(?:\\%)|[^%\n])*)(.*)$', re.M)
self.graphics_extensions = graphics_extensions
@@ -236,23 +268,26 @@ class LaTeX(SCons.Scanner.Base):
SCons.Scanner.Base.__init__(self, *args, **kw)
- def _latex_names(self, include):
- filename = include[1]
- if include[0] == 'input':
+ def _latex_names(self, include_type, filename):
+ if include_type == 'input':
+ base, ext = os.path.splitext( filename )
+ if ext == "":
+ return [filename + '.tex']
+ if include_type in ('include', 'import', 'subimport',
+ 'includefrom', 'subincludefrom',
+ 'inputfrom', 'subinputfrom'):
base, ext = os.path.splitext( filename )
if ext == "":
return [filename + '.tex']
- if (include[0] == 'include'):
- return [filename + '.tex']
- if include[0] == 'bibliography':
+ if include_type == 'bibliography':
base, ext = os.path.splitext( filename )
if ext == "":
return [filename + '.bib']
- if include[0] == 'usepackage':
+ if include_type == 'usepackage':
base, ext = os.path.splitext( filename )
if ext == "":
return [filename + '.sty']
- if include[0] == 'includegraphics':
+ if include_type == 'includegraphics':
base, ext = os.path.splitext( filename )
if ext == "":
#return [filename+e for e in self.graphics_extensions + TexGraphics]
@@ -267,21 +302,26 @@ class LaTeX(SCons.Scanner.Base):
return SCons.Node.FS._my_normcase(str(include))
def find_include(self, include, source_dir, path):
+ inc_type, inc_subdir, inc_filename = include
try:
- sub_path = path[include[0]]
+ sub_paths = path[inc_type]
except (IndexError, KeyError):
- sub_path = ()
- try_names = self._latex_names(include)
+ sub_paths = ((), ())
+ try_names = self._latex_names(inc_type, inc_filename)
+
+ # There are three search paths to try:
+ # 1. current directory "source_dir"
+ # 2. env[var]
+ # 3. env['ENV'][var]
+ search_paths = [(source_dir,)] + list(sub_paths)
+
for n in try_names:
- # see if we find it using the path in env[var]
- i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[0])
- if i:
- return i, include
- # see if we find it using the path in env['ENV'][var]
- i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[1])
- if i:
- return i, include
- return i, include
+ for search_path in search_paths:
+ paths = tuple([d.Dir(inc_subdir) for d in search_path])
+ i = SCons.Node.FS.find_file(n, paths)
+ if i:
+ return i, include
+ return None, include
def canonical_text(self, text):
"""Standardize an input TeX-file contents.
@@ -300,7 +340,7 @@ class LaTeX(SCons.Scanner.Base):
line_continues_a_comment = len(comment) > 0
return '\n'.join(out).rstrip()+'\n'
- def scan(self, node):
+ def scan(self, node, subdir='.'):
# Modify the default scan function to allow for the regular
# expression to return a comma separated list of file names
# as can be the case with the bibliography keyword.
@@ -326,9 +366,14 @@ class LaTeX(SCons.Scanner.Base):
split_includes = []
for include in includes:
inc_type = noopt_cre.sub('', include[0])
- inc_list = include[1].split(',')
+ inc_subdir = subdir
+ if inc_type in self.two_arg_commands:
+ inc_subdir = os.path.join(subdir, include[1])
+ inc_list = include[2].split(',')
+ else:
+ inc_list = include[1].split(',')
for j in range(len(inc_list)):
- split_includes.append( (inc_type, inc_list[j]) )
+ split_includes.append( (inc_type, inc_subdir, inc_list[j]) )
#
includes = split_includes
node.includes = includes
@@ -359,11 +404,13 @@ class LaTeX(SCons.Scanner.Base):
while queue:
include = queue.pop()
+ inc_type, inc_subdir, inc_filename = include
+
try:
- if seen[include[1]] == 1:
+ if seen[inc_filename] == 1:
continue
except KeyError:
- seen[include[1]] = 1
+ seen[inc_filename] = 1
#
# Handle multiple filenames in include[1]
@@ -372,14 +419,14 @@ class LaTeX(SCons.Scanner.Base):
if n is None:
# Do not bother with 'usepackage' warnings, as they most
# likely refer to system-level files
- if include[0] != 'usepackage':
+ if inc_type != 'usepackage':
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
"No dependency generated for file: %s (included from: %s) -- file not found" % (i, node))
else:
sortkey = self.sort_key(n)
nodes.append((sortkey, n))
- # recurse down
- queue.extend( self.scan(n) )
+ # recurse down
+ queue.extend( self.scan(n, inc_subdir) )
return [pair[1] for pair in sorted(nodes)]