Several improvements to the latex builder.

This commit is contained in:
Georg Brandl 2007-12-16 19:36:23 +00:00
parent d6deb877df
commit fbe9ed59cb
8 changed files with 130 additions and 27 deletions

View File

@ -64,10 +64,13 @@ class literal_emphasis(nodes.emphasis): pass
# glossary # glossary
class glossary(nodes.Element): pass class glossary(nodes.Element): pass
# module declaration
class module(nodes.Element): pass
# make them known to docutils. this is needed, because the HTMl writer # make them known to docutils. this is needed, because the HTMl writer
# will choke at some point if these are not added # will choke at some point if these are not added
nodes._add_node_class_names("""index desc desc_content desc_signature desc_type nodes._add_node_class_names("""index desc desc_content desc_signature desc_type
desc_classname desc_name desc_parameterlist desc_parameter desc_optional desc_classname desc_name desc_parameterlist desc_parameter desc_optional
centered versionmodified seealso productionlist production toctree centered versionmodified seealso productionlist production toctree
pending_xref compact_paragraph highlightlang literal_emphasis pending_xref compact_paragraph highlightlang literal_emphasis
glossary acks""".split()) glossary acks module""".split())

View File

@ -223,8 +223,6 @@ class Builder(object):
# global actions # global actions
self.msg('checking consistency...') self.msg('checking consistency...')
self.env.check_consistency() self.env.check_consistency()
self.msg('creating index...')
self.env.create_index(self)
# another indirection to support methods which don't build files # another indirection to support methods which don't build files
# individually # individually
@ -236,6 +234,8 @@ class Builder(object):
self.msg('done!') self.msg('done!')
def write(self, filenames): def write(self, filenames):
self.msg('creating index...')
self.env.create_index(self)
if filenames: if filenames:
# add all TOC files that may have changed # add all TOC files that may have changed
filenames_set = set(filenames) filenames_set = set(filenames)
@ -314,7 +314,7 @@ class StandaloneHTMLBuilder(Builder):
# format the "last updated on" string, only once is enough since it # format the "last updated on" string, only once is enough since it
# typically doesn't include the time of day # typically doesn't include the time of day
lufmt = self.config.get('last_updated_format') lufmt = self.config.get('html_last_updated_fmt')
if lufmt: if lufmt:
self.last_updated = time.strftime(lufmt) self.last_updated = time.strftime(lufmt)
else: else:
@ -446,7 +446,7 @@ class StandaloneHTMLBuilder(Builder):
downloadcontext = dict( downloadcontext = dict(
pathto = relpath_to(self, self.get_target_uri('download.rst')), pathto = relpath_to(self, self.get_target_uri('download.rst')),
current_page_name = 'download', current_page_name = 'download',
download_base_url = self.config['download_base_url'], download_base_url = self.config['html_download_base_url'],
) )
self.handle_file('download.rst', downloadcontext, 'download') self.handle_file('download.rst', downloadcontext, 'download')
@ -490,8 +490,8 @@ class StandaloneHTMLBuilder(Builder):
for filename in get_matching_files( for filename in get_matching_files(
self.srcdir, '*.rst', exclude=set(self.config.get('unused_files', ()))): self.srcdir, '*.rst', exclude=set(self.config.get('unused_files', ()))):
try: try:
targetmtime = path.getmtime(path.join(self.outdir, rstname = path.join(self.outdir, os_path(filename))
os_path(filename)[:-4] + '.html')) targetmtime = path.getmtime(rstname[:-4] + '.html')
except: except:
targetmtime = 0 targetmtime = 0
if filename not in self.env.all_files: if filename not in self.env.all_files:
@ -652,7 +652,7 @@ class LaTeXBuilder(Builder):
def get_outdated_files(self): def get_outdated_files(self):
# XXX always rebuild everything for now # XXX always rebuild everything for now
return self.env.all_files return ['dummy']
def get_target_uri(self, source_filename, typ=None): def get_target_uri(self, source_filename, typ=None):
if typ == 'token': if typ == 'token':
@ -665,6 +665,7 @@ class LaTeXBuilder(Builder):
return '' return ''
def get_document_data(self): def get_document_data(self):
# Python specific...
for toplevel in ["c-api", "distutils", "documenting", "extending", for toplevel in ["c-api", "distutils", "documenting", "extending",
"install", "reference", "tutorial", "using", "library"]: "install", "reference", "tutorial", "using", "library"]:
yield (toplevel + SEP + 'index.rst', toplevel+'.tex', 'manual') yield (toplevel + SEP + 'index.rst', toplevel+'.tex', 'manual')

View File

@ -518,11 +518,14 @@ def module_directive(name, arguments, options, content, lineno,
env.note_module(modname, options.get('synopsis', ''), env.note_module(modname, options.get('synopsis', ''),
options.get('platform', ''), options.get('platform', ''),
'deprecated' in options) 'deprecated' in options)
ret = [] modulenode = addnodes.module()
modulenode['modname'] = modname
modulenode['synopsis'] = options.get('synopsis', '')
targetnode = nodes.target('', '', ids=['module-' + modname]) targetnode = nodes.target('', '', ids=['module-' + modname])
state.document.note_explicit_target(targetnode) state.document.note_explicit_target(targetnode)
ret.append(targetnode) ret = [modulenode, targetnode]
if 'platform' in options: if 'platform' in options:
modulenode['platform'] = options['platform']
node = nodes.paragraph() node = nodes.paragraph()
node += nodes.emphasis('Platforms: ', 'Platforms: ') node += nodes.emphasis('Platforms: ', 'Platforms: ')
node += nodes.Text(options['platform'], options['platform']) node += nodes.Text(options['platform'], options['platform'])

View File

@ -260,7 +260,7 @@ class BuildEnvironment:
new = [change for change in changes if change[1] != filename] new = [change for change in changes if change[1] != filename]
changes[:] = new changes[:] = new
def get_outdated_files(self, config): def get_outdated_files(self, config, config_changed):
""" """
Return (added, changed, removed) iterables. Return (added, changed, removed) iterables.
""" """
@ -273,7 +273,7 @@ class BuildEnvironment:
added = [] added = []
changed = [] changed = []
if config != self.config: if config_changed:
# config values affect e.g. substitutions # config values affect e.g. substitutions
added = all_source_files added = all_source_files
else: else:
@ -298,6 +298,11 @@ class BuildEnvironment:
return added, changed, removed return added, changed, removed
# If one of these config values changes, all files need to be re-read.
influential_config_values = [
'version', 'release', 'today', 'today_fmt', 'unused_files'
]
def update(self, config): def update(self, config):
""" """
(Re-)read all files new or changed since last update. (Re-)read all files new or changed since last update.
@ -305,11 +310,17 @@ class BuildEnvironment:
Store all environment filenames in the canonical format Store all environment filenames in the canonical format
(ie using SEP as a separator in place of os.path.sep). (ie using SEP as a separator in place of os.path.sep).
""" """
added, changed, removed = self.get_outdated_files(config) config_changed = False
msg = '%s added, %s changed, %s removed' % (len(added), len(changed), for val in self.influential_config_values:
len(removed)) if self.config.get(val) != config.get(val):
if self.config != config: msg = '[config changed] '
msg = '[config changed] ' + msg config_changed = True
break
else:
msg = ''
added, changed, removed = self.get_outdated_files(config, config_changed)
msg += '%s added, %s changed, %s removed' % (len(added), len(changed),
len(removed))
yield msg yield msg
self.config = config self.config = config

View File

@ -232,6 +232,11 @@ def translator_class(config, buildername):
def depart_acks(self, node): def depart_acks(self, node):
pass pass
def visit_module(self, node):
pass
def depart_module(self, node):
pass
# these are only handled specially in the SmartyPantsHTMLTranslator # these are only handled specially in the SmartyPantsHTMLTranslator
def visit_literal_emphasis(self, node): def visit_literal_emphasis(self, node):
return self.visit_emphasis(node) return self.visit_emphasis(node)
@ -297,7 +302,7 @@ def translator_class(config, buildername):
text = sphinx_smarty_pants(text) text = sphinx_smarty_pants(text)
return text return text
if config.get('use_smartypants', False): if config.get('html_use_smartypants', False):
return SmartyPantsHTMLTranslator return SmartyPantsHTMLTranslator
else: else:
return HTMLTranslator return HTMLTranslator

View File

@ -36,10 +36,11 @@ HEADER = r'''%% Generated by Sphinx.
Email: \email{docs@python.org} Email: \email{docs@python.org}
} }
\makeindex \makeindex
\makemodindex
''' '''
FOOTER = r''' FOOTER = r'''
\printmodindex
\printindex \printindex
\end{document} \end{document}
''' '''
@ -93,9 +94,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
nodes.NodeVisitor.__init__(self, document) nodes.NodeVisitor.__init__(self, document)
self.body = [] self.body = []
docclass = document.settings.docclass docclass = document.settings.docclass
paper = config.get('latex_paper_size', 'letter') + 'paper'
if paper == 'paper': # e.g. command line "-D latex_paper_size="
paper = 'letterpaper'
self.options = {'docclass': docclass, self.options = {'docclass': docclass,
'papersize': 'a4paper', # XXX 'papersize': paper,
'pointsize': '12pt', 'pointsize': config.get('latex_font_size', '10pt'),
'filename': document.settings.filename, 'filename': document.settings.filename,
'title': None, # is determined later 'title': None, # is determined later
'release': config['release'], 'release': config['release'],
@ -150,6 +154,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_section(self, node): def depart_section(self, node):
self.sectionlevel -= 1 self.sectionlevel -= 1
def visit_problematic(self, node):
self.body.append('{\\color{red}\\bfseries{}')
def depart_problematic(self, node):
self.body.append('}')
def visit_topic(self, node): def visit_topic(self, node):
raise nodes.SkipNode # XXX raise nodes.SkipNode # XXX
@ -425,11 +434,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass pass
def visit_term(self, node): def visit_term(self, node):
ctx = ']'
if node.has_key('ids') and node['ids']: if node.has_key('ids') and node['ids']:
self.body.append('\\hypertarget{%s}{}' % node['ids'][0]) ctx += '\\hypertarget{%s}{}' % node['ids'][0]
self.body.append('\\item[') self.body.append('\\item[')
self.context.append(ctx)
def depart_term(self, node): def depart_term(self, node):
self.body.append(']\n') self.body.append(self.context.pop())
def visit_classifier(self, node): def visit_classifier(self, node):
self.body.append('{[}') self.body.append('{[}')
@ -451,6 +462,16 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_centered(self, node): def depart_centered(self, node):
self.body.append('\n\\end{centering}') self.body.append('\n\\end{centering}')
def visit_module(self, node):
modname = node['modname']
self.body.append('\\declaremodule[%s]{}{%s}' % (modname.replace('_', ''),
self.encode(modname)))
self.body.append('\\modulesynopsis{%s}' % self.encode(node['synopsis']))
if node.has_key('platform'):
self.body.append('\\platform{%s}' % self.encode(node['platform']))
def depart_module(self, node):
pass
def visit_note(self, node): def visit_note(self, node):
self.body.append('\n\\begin{notice}[note]') self.body.append('\n\\begin{notice}[note]')
def depart_note(self, node): def depart_note(self, node):
@ -485,9 +506,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
return '}' return '}'
return '' return ''
# XXX specialcase 'module-' targets: add \declaremodule
# XXX where to put \makemodindex
if not (node.has_key('refuri') or node.has_key('refid') if not (node.has_key('refuri') or node.has_key('refid')
or node.has_key('refname')): or node.has_key('refname')):
ctx = '' ctx = ''
@ -505,7 +523,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(self.context.pop()) self.body.append(self.context.pop())
indextype_map = { indextype_map = {
'module': 'refmodindex', # XXX: key?
'keyword': 'kwindex', 'keyword': 'kwindex',
'operator': 'opindex', 'operator': 'opindex',
'object': 'obindex', 'object': 'obindex',
@ -525,6 +542,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
elif type == 'triple': elif type == 'triple':
parts = tuple(self.encode(x.strip()) for x in string.split(';', 2)) parts = tuple(self.encode(x.strip()) for x in string.split(';', 2))
self.body.append(r'\indexiii{%s}{%s}{%s}' % parts) self.body.append(r'\indexiii{%s}{%s}{%s}' % parts)
elif type == 'module':
self.body.append(r'\refmodindex[%s]{%s}' % (string.replace('_', ''),
self.encode(string)))
elif type in self.indextype_map: elif type in self.indextype_map:
self.body.append(r'\%s{%s}' % (self.indextype_map[type], self.body.append(r'\%s{%s}' % (self.indextype_map[type],
self.encode(string))) self.encode(string)))
@ -656,7 +676,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
(u"]", ur"{]}"), (u"]", ur"{]}"),
(u"", ur"\P{}"), (u"", ur"\P{}"),
(u"§", ur"\S{}"), (u"§", ur"\S{}"),
(u"", ur"$\infinity$"),
(u"±", ur"$\pm$"),
(u"", ur"$\rightarrow$"),
(u"", ur"$\Omega$"),
(u"Ω", ur"$\Omega$"),
(u"~", ur"\textasciitilde{}"), (u"~", ur"\textasciitilde{}"),
(u"", ur"\texteuro{}"),
(u"<", ur"\textless{}"), (u"<", ur"\textless{}"),
(u">", ur"\textgreater{}"), (u">", ur"\textgreater{}"),
(u"^", ur"\textasciicircum{}"), (u"^", ur"\textasciicircum{}"),

50
sphinx/texinputs/Makefile Normal file
View File

@ -0,0 +1,50 @@
# Makefile for Sphinx LaTeX output
ALLDOCS = $(basename $(wildcard *.tex))
ALLPDF = $(addsuffix .pdf,$(ALLDOCS))
ALLDVI = $(addsuffix .dvi,$(ALLDOCS))
# Prefix for archive names
ARCHIVEPRREFIX =
all: $(ALLPDF)
all-pdf: $(ALLPDF)
all-dvi: $(ALLDVI)
all-ps: all-dvi
for f in *.dvi; do dvips $f; done
zip: all-$(FMT)
mkdir $(ARCHIVEPREFIX)docs-$(FMT)
cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT)
zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT)
rm -r $(ARCHIVEPREFIX)docs-$(FMT)
tar: all-$(FMT)
mkdir $(ARCHIVEPREFIX)docs-$(FMT)
cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT)
tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar
rm -r $(ARCHIVEPREFIX)docs-$(FMT)
bz2: tar-$(FMT)
bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar
%.dvi: %.tex
latex $<
latex $<
latex $<
-makeindex -s python.ist $(basename $<).idx
-makeindex -s python.ist $(basename mod$<).idx
latex $<
latex $<
%.pdf: %.tex
pdflatex $<
pdflatex $<
pdflatex $<
-makeindex -s python.ist $(basename $<).idx
-makeindex -s python.ist $(basename mod$<).idx
pdflatex $<
pdflatex $<
.PHONY: all all-pdf all-dvi all-ps

View File

@ -330,6 +330,10 @@
\py@UseModuleIndextrue \py@UseModuleIndextrue
} }
\newcommand{\printmodindex}{
\@input@{mod\jobname.ind}
}
% Add the defining entry for a module % Add the defining entry for a module
\newcommand{\py@modindex}[2]{% \newcommand{\py@modindex}[2]{%
\renewcommand{\py@thismodule}{#1} \renewcommand{\py@thismodule}{#1}