|
Packit Service |
76cb02 |
# This file is part of Rubber and thus covered by the GPL
|
|
Packit Service |
76cb02 |
# (c) Emmanuel Beffara, 2002--2006
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
LaTeX document building system for Rubber.
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
This module defines the class that parses the input LaTeX to load the expected
|
|
Packit Service |
76cb02 |
modules.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
import re
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
class TexParser:
|
|
Packit Service |
76cb02 |
re_input = re.compile("\\\\input +(?P<arg>[^{} \n\\\\]+)")
|
|
Packit Service |
76cb02 |
re_comment = re.compile(r"(?P<line>([^\\%]|\\%|\\)*)(%.*)?")
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def __init__(self, doc):
|
|
Packit Service |
76cb02 |
self.doc = doc
|
|
Packit Service |
76cb02 |
self.comment_mark = "%"
|
|
Packit Service |
76cb02 |
self.exclude_mods = []
|
|
Packit Service |
76cb02 |
self.hooks = {
|
|
Packit Service |
76cb02 |
"usepackage" : self.h_usepackage,
|
|
Packit Service |
76cb02 |
"begin{btSect}": self.h_bibtopic,
|
|
Packit Service |
76cb02 |
}
|
|
Packit Service |
76cb02 |
self.update_rehooks()
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def update_rehooks(self):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
Update the regular expression used to match macro calls using the keys
|
|
Packit Service |
76cb02 |
in the `hook' dictionary. We don't match all control sequences for
|
|
Packit Service |
76cb02 |
obvious efficiency reasons.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
# Make a "foo|bar\*stub" list
|
|
Packit Service |
76cb02 |
hooklist = [x.replace("*", "\\*") for x in self.hooks]
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
pattern = "\\\\(?P<name>%s)\*?"\
|
|
Packit Service |
76cb02 |
" *(\\[(?P<opt>[^\\]]*)\\])?"\
|
|
Packit Service |
76cb02 |
" *({(?P<arg>[^{}]*)}|(?=[^A-Za-z]))"
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
self.rehooks = re.compile(pattern % "|".join(hooklist))
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def add_hook(self, name, fun):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
Register a given function to be called (with no arguments) when a
|
|
Packit Service |
76cb02 |
given macro is found.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
self.hooks[name] = fun
|
|
Packit Service |
76cb02 |
self.update_rehooks()
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def parse(self, fd, exclude_mods=None):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
Process a LaTeX source. The file must be open, it is read to the end
|
|
Packit Service |
76cb02 |
calling the handlers for the macro calls. This recursively processes
|
|
Packit Service |
76cb02 |
the included sources.
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
If the optional argument 'dump' is not None, then it is considered as
|
|
Packit Service |
76cb02 |
a stream on which all text not matched as a macro is written.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
self.exclude_mods = exclude_mods or []
|
|
Packit Service |
76cb02 |
self.lineno = 0
|
|
Packit Service |
76cb02 |
for line in fd:
|
|
Packit Service |
76cb02 |
self.parse_line(line)
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def parse_line(self, line, dump=None):
|
|
Packit Service |
76cb02 |
self.lineno += 1
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
# Remove comments
|
|
Packit Service |
76cb02 |
line = self.re_comment.match(line).group("line")
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
match = self.rehooks.search(line)
|
|
Packit Service |
76cb02 |
while match:
|
|
Packit Service |
76cb02 |
dict = match.groupdict()
|
|
Packit Service |
76cb02 |
name = dict["name"]
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
# The case of \input is handled specifically, because of the
|
|
Packit Service |
76cb02 |
# TeX syntax with no braces
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
if name == "input" and not dict["arg"]:
|
|
Packit Service |
76cb02 |
match2 = self.re_input.search(line)
|
|
Packit Service |
76cb02 |
if match2:
|
|
Packit Service |
76cb02 |
match = match2
|
|
Packit Service |
76cb02 |
dict = match.groupdict()
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
if dump: dump.write(line[:match.start()])
|
|
Packit Service |
76cb02 |
dict["match"] = line[match.start():match.end()]
|
|
Packit Service |
76cb02 |
dict["line"] = line[match.end():]
|
|
Packit Service |
76cb02 |
#dict["pos"] = { 'file': self.vars["file"], 'line': self.lineno }
|
|
Packit Service |
76cb02 |
dict["pos"] = { 'file': "file", 'line': self.lineno }
|
|
Packit Service |
76cb02 |
dict["dump"] = dump
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
# if self.env.caching:
|
|
Packit Service |
76cb02 |
# self.cache_list.append(("hook", name, dict))
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
self.hooks[name](dict)
|
|
Packit Service |
76cb02 |
line = dict["line"]
|
|
Packit Service |
76cb02 |
match = self.rehooks.search(line)
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
if dump: dump.write(line)
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def h_usepackage(self, dict):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
Called when a \\usepackage macro is found. If there is a package in the
|
|
Packit Service |
76cb02 |
directory of the source file, then it is treated as an include file
|
|
Packit Service |
76cb02 |
unless there is a supporting module in the current directory,
|
|
Packit Service |
76cb02 |
otherwise it is treated as a package.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
if not dict["arg"]: return
|
|
Packit Service |
76cb02 |
for name in dict["arg"].split(","):
|
|
Packit Service |
76cb02 |
name = name.strip()
|
|
Packit Service |
76cb02 |
# file = self.env.find_file(name + ".sty")
|
|
Packit Service |
76cb02 |
# if file and not exists(name + ".py"):
|
|
Packit Service |
76cb02 |
# self.process(file)
|
|
Packit Service |
76cb02 |
# else:
|
|
Packit Service |
76cb02 |
if (name in self.exclude_mods):
|
|
Packit Service |
76cb02 |
continue
|
|
Packit Service |
76cb02 |
self.doc.modules.register(name, dict)
|
|
Packit Service |
76cb02 |
|
|
Packit Service |
76cb02 |
def h_bibtopic(self, dict):
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
Called when a \\btSect macro is found. It can also be loaded by a
|
|
Packit Service |
76cb02 |
usepackage of bibtopic. Note that once loaded the btSect hook will be
|
|
Packit Service |
76cb02 |
preempted by the bibtopic module hook.
|
|
Packit Service |
76cb02 |
"""
|
|
Packit Service |
76cb02 |
if ("bibtopic" in self.exclude_mods):
|
|
Packit Service |
76cb02 |
return
|
|
Packit Service |
76cb02 |
self.doc.modules.register("bibtopic", dict)
|
|
Packit Service |
76cb02 |
|