diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py index 6fecb92f9..1a49a6828 100644 --- a/sphinx/addnodes.py +++ b/sphinx/addnodes.py @@ -64,10 +64,13 @@ class literal_emphasis(nodes.emphasis): pass # glossary class glossary(nodes.Element): pass +# module declaration +class module(nodes.Element): pass + # make them known to docutils. this is needed, because the HTMl writer # will choke at some point if these are not added nodes._add_node_class_names("""index desc desc_content desc_signature desc_type desc_classname desc_name desc_parameterlist desc_parameter desc_optional centered versionmodified seealso productionlist production toctree pending_xref compact_paragraph highlightlang literal_emphasis - glossary acks""".split()) + glossary acks module""".split()) diff --git a/sphinx/builder.py b/sphinx/builder.py index a864db214..1de29d645 100644 --- a/sphinx/builder.py +++ b/sphinx/builder.py @@ -223,8 +223,6 @@ class Builder(object): # global actions self.msg('checking consistency...') self.env.check_consistency() - self.msg('creating index...') - self.env.create_index(self) # another indirection to support methods which don't build files # individually @@ -236,6 +234,8 @@ class Builder(object): self.msg('done!') def write(self, filenames): + self.msg('creating index...') + self.env.create_index(self) if filenames: # add all TOC files that may have changed filenames_set = set(filenames) @@ -314,7 +314,7 @@ class StandaloneHTMLBuilder(Builder): # format the "last updated on" string, only once is enough since it # 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: self.last_updated = time.strftime(lufmt) else: @@ -446,7 +446,7 @@ class StandaloneHTMLBuilder(Builder): downloadcontext = dict( pathto = relpath_to(self, self.get_target_uri('download.rst')), 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') @@ -490,8 +490,8 @@ class StandaloneHTMLBuilder(Builder): for filename in get_matching_files( self.srcdir, '*.rst', exclude=set(self.config.get('unused_files', ()))): try: - targetmtime = path.getmtime(path.join(self.outdir, - os_path(filename)[:-4] + '.html')) + rstname = path.join(self.outdir, os_path(filename)) + targetmtime = path.getmtime(rstname[:-4] + '.html') except: targetmtime = 0 if filename not in self.env.all_files: @@ -652,7 +652,7 @@ class LaTeXBuilder(Builder): def get_outdated_files(self): # XXX always rebuild everything for now - return self.env.all_files + return ['dummy'] def get_target_uri(self, source_filename, typ=None): if typ == 'token': @@ -665,6 +665,7 @@ class LaTeXBuilder(Builder): return '' def get_document_data(self): + # Python specific... for toplevel in ["c-api", "distutils", "documenting", "extending", "install", "reference", "tutorial", "using", "library"]: yield (toplevel + SEP + 'index.rst', toplevel+'.tex', 'manual') diff --git a/sphinx/directives.py b/sphinx/directives.py index ca9cf856c..d89b170fb 100644 --- a/sphinx/directives.py +++ b/sphinx/directives.py @@ -518,11 +518,14 @@ def module_directive(name, arguments, options, content, lineno, env.note_module(modname, options.get('synopsis', ''), options.get('platform', ''), 'deprecated' in options) - ret = [] + modulenode = addnodes.module() + modulenode['modname'] = modname + modulenode['synopsis'] = options.get('synopsis', '') targetnode = nodes.target('', '', ids=['module-' + modname]) state.document.note_explicit_target(targetnode) - ret.append(targetnode) + ret = [modulenode, targetnode] if 'platform' in options: + modulenode['platform'] = options['platform'] node = nodes.paragraph() node += nodes.emphasis('Platforms: ', 'Platforms: ') node += nodes.Text(options['platform'], options['platform']) diff --git a/sphinx/environment.py b/sphinx/environment.py index ac95feab7..1d34fc186 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -260,7 +260,7 @@ class BuildEnvironment: new = [change for change in changes if change[1] != filename] changes[:] = new - def get_outdated_files(self, config): + def get_outdated_files(self, config, config_changed): """ Return (added, changed, removed) iterables. """ @@ -273,7 +273,7 @@ class BuildEnvironment: added = [] changed = [] - if config != self.config: + if config_changed: # config values affect e.g. substitutions added = all_source_files else: @@ -298,6 +298,11 @@ class BuildEnvironment: 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): """ (Re-)read all files new or changed since last update. @@ -305,11 +310,17 @@ class BuildEnvironment: Store all environment filenames in the canonical format (ie using SEP as a separator in place of os.path.sep). """ - added, changed, removed = self.get_outdated_files(config) - msg = '%s added, %s changed, %s removed' % (len(added), len(changed), - len(removed)) - if self.config != config: - msg = '[config changed] ' + msg + config_changed = False + for val in self.influential_config_values: + if self.config.get(val) != config.get(val): + msg = '[config changed] ' + 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 self.config = config diff --git a/sphinx/htmlwriter.py b/sphinx/htmlwriter.py index 8468e7aff..f6a60b9ea 100644 --- a/sphinx/htmlwriter.py +++ b/sphinx/htmlwriter.py @@ -232,6 +232,11 @@ def translator_class(config, buildername): def depart_acks(self, node): pass + def visit_module(self, node): + pass + def depart_module(self, node): + pass + # these are only handled specially in the SmartyPantsHTMLTranslator def visit_literal_emphasis(self, node): return self.visit_emphasis(node) @@ -297,7 +302,7 @@ def translator_class(config, buildername): text = sphinx_smarty_pants(text) return text - if config.get('use_smartypants', False): + if config.get('html_use_smartypants', False): return SmartyPantsHTMLTranslator else: return HTMLTranslator diff --git a/sphinx/latexwriter.py b/sphinx/latexwriter.py index efc0a3462..63afd2866 100644 --- a/sphinx/latexwriter.py +++ b/sphinx/latexwriter.py @@ -36,10 +36,11 @@ HEADER = r'''%% Generated by Sphinx. Email: \email{docs@python.org} } \makeindex - +\makemodindex ''' FOOTER = r''' +\printmodindex \printindex \end{document} ''' @@ -93,9 +94,12 @@ class LaTeXTranslator(nodes.NodeVisitor): nodes.NodeVisitor.__init__(self, document) self.body = [] 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, - 'papersize': 'a4paper', # XXX - 'pointsize': '12pt', + 'papersize': paper, + 'pointsize': config.get('latex_font_size', '10pt'), 'filename': document.settings.filename, 'title': None, # is determined later 'release': config['release'], @@ -150,6 +154,11 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_section(self, node): 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): raise nodes.SkipNode # XXX @@ -425,11 +434,13 @@ class LaTeXTranslator(nodes.NodeVisitor): pass def visit_term(self, node): + ctx = ']' 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.context.append(ctx) def depart_term(self, node): - self.body.append(']\n') + self.body.append(self.context.pop()) def visit_classifier(self, node): self.body.append('{[}') @@ -451,6 +462,16 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_centered(self, node): 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): self.body.append('\n\\begin{notice}[note]') def depart_note(self, node): @@ -485,9 +506,6 @@ class LaTeXTranslator(nodes.NodeVisitor): return '}' return '' - # XXX specialcase 'module-' targets: add \declaremodule - # XXX where to put \makemodindex - if not (node.has_key('refuri') or node.has_key('refid') or node.has_key('refname')): ctx = '' @@ -505,7 +523,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append(self.context.pop()) indextype_map = { - 'module': 'refmodindex', # XXX: key? 'keyword': 'kwindex', 'operator': 'opindex', 'object': 'obindex', @@ -525,6 +542,9 @@ class LaTeXTranslator(nodes.NodeVisitor): elif type == 'triple': parts = tuple(self.encode(x.strip()) for x in string.split(';', 2)) 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: self.body.append(r'\%s{%s}' % (self.indextype_map[type], self.encode(string))) @@ -656,7 +676,13 @@ class LaTeXTranslator(nodes.NodeVisitor): (u"]", ur"{]}"), (u"¶", ur"\P{}"), (u"§", ur"\S{}"), + (u"∞", ur"$\infinity$"), + (u"±", ur"$\pm$"), + (u"‣", ur"$\rightarrow$"), + (u"Ω", ur"$\Omega$"), + (u"Ω", ur"$\Omega$"), (u"~", ur"\textasciitilde{}"), + (u"€", ur"\texteuro{}"), (u"<", ur"\textless{}"), (u">", ur"\textgreater{}"), (u"^", ur"\textasciicircum{}"), diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile new file mode 100644 index 000000000..c01faa47c --- /dev/null +++ b/sphinx/texinputs/Makefile @@ -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 + diff --git a/sphinx/texinputs/python.sty b/sphinx/texinputs/python.sty index 9ae7dd574..572a6fbc5 100644 --- a/sphinx/texinputs/python.sty +++ b/sphinx/texinputs/python.sty @@ -330,6 +330,10 @@ \py@UseModuleIndextrue } +\newcommand{\printmodindex}{ + \@input@{mod\jobname.ind} +} + % Add the defining entry for a module \newcommand{\py@modindex}[2]{% \renewcommand{\py@thismodule}{#1}