diff options
| author | Georg Brandl <georg@python.org> | 2010-02-20 01:13:23 +0100 |
|---|---|---|
| committer | Georg Brandl <georg@python.org> | 2010-02-20 01:13:23 +0100 |
| commit | 69af046cfcbadba827d8301a7bfaa2c4f1e5d3a8 (patch) | |
| tree | 4cb0f9cd3897bf61524e76eb51f3d313f0157f0e /sphinx | |
| parent | 71a29487ac88b6b48ae62cbad1c97de561cabe06 (diff) | |
| download | sphinx-69af046cfcbadba827d8301a7bfaa2c4f1e5d3a8.tar.gz | |
Make the concept of "module index" generalized to domains. As a side-effect, the latex modindex is no longer generated by LaTeX.
Diffstat (limited to 'sphinx')
| -rw-r--r-- | sphinx/builders/html.py | 129 | ||||
| -rw-r--r-- | sphinx/builders/htmlhelp.py | 6 | ||||
| -rw-r--r-- | sphinx/builders/qthelp.py | 6 | ||||
| -rw-r--r-- | sphinx/config.py | 6 | ||||
| -rw-r--r-- | sphinx/domains/__init__.py | 18 | ||||
| -rw-r--r-- | sphinx/domains/python.py | 80 | ||||
| -rw-r--r-- | sphinx/environment.py | 12 | ||||
| -rw-r--r-- | sphinx/quickstart.py | 4 | ||||
| -rw-r--r-- | sphinx/texinputs/Makefile | 2 | ||||
| -rw-r--r-- | sphinx/texinputs/sphinx.sty | 83 | ||||
| -rw-r--r-- | sphinx/themes/basic/domainindex.html | 54 | ||||
| -rw-r--r-- | sphinx/themes/basic/layout.html | 2 | ||||
| -rw-r--r-- | sphinx/themes/basic/modindex.html | 52 | ||||
| -rw-r--r-- | sphinx/themes/basic/static/doctools.js | 8 | ||||
| -rw-r--r-- | sphinx/util/texescape.py | 2 | ||||
| -rw-r--r-- | sphinx/writers/latex.py | 120 |
16 files changed, 287 insertions, 297 deletions
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 7f4e4c66..c722a195 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -230,6 +230,20 @@ class StandaloneHTMLBuilder(Builder): defaults=self.env.settings, components=(self.docwriter,)).get_default_values() + # determine the additional indices to include + self.domain_indices = [] + # html_domain_indices can be False/True or a list of index names + indices_config = self.config.html_domain_indices + if indices_config: + for domain in self.env.domains.itervalues(): + for indexinfo in domain.indices: + indexname = '%s-%s' % (domain.name, indexinfo[0]) + if isinstance(indices_config, list): + if indexname not in indices_config: + continue + if domain.has_index_entries(indexinfo[0]): + self.domain_indices.append((domain.name,) + indexinfo) + # format the "last updated on" string, only once is enough since it # typically doesn't include the time of day lufmt = self.config.html_last_updated_fmt @@ -254,11 +268,8 @@ class StandaloneHTMLBuilder(Builder): rellinks = [] if self.config.html_use_index: rellinks.append(('genindex', _('General Index'), 'I', _('index'))) - # XXX generalization of modindex? - if self.config.html_use_modindex and \ - self.env.domaindata['py']['modules']: - rellinks.append(('modindex', _('Global Module Index'), - 'M', _('modules'))) + for index in self.domain_indices: + rellinks.append(('%s-%s' % index[0:2], index[2], '', index[3])) if self.config.html_style is not None: stylename = self.config.html_style @@ -396,9 +407,8 @@ class StandaloneHTMLBuilder(Builder): if self.config.html_use_index: self.write_genindex() - # the global module index - if self.config.html_use_modindex: - self.write_modindex() + # the global domain-specific indices + self.write_domain_indices() # the search page if self.name != 'htmlhelp': @@ -454,98 +464,17 @@ class StandaloneHTMLBuilder(Builder): else: self.handle_page('genindex', genindexcontext, 'genindex.html') - def write_modindex(self): - moduleindex = self.env.domaindata['py']['modules'] - if not moduleindex: - return - # the sorted list of all modules, for the global module index - modules = sorted(((mn, (self.get_relative_uri('modindex', fn) + - '#module-' + mn, sy, pl, dep)) - for (mn, (fn, sy, pl, dep)) in - moduleindex.iteritems()), - key=lambda x: x[0].lower()) - # collect all platforms - platforms = set() - # sort out collapsable modules - modindexentries = [] - letters = [] - pmn = '' - num_toplevels = 0 - num_collapsables = 0 - cg = 0 # collapse group - fl = '' # first letter - for mn, (fn, sy, pl, dep) in modules: - pl = pl and pl.split(', ') or [] - platforms.update(pl) - - ignore = self.env.config['modindex_common_prefix'] - ignore = sorted(ignore, key=len, reverse=True) - for i in ignore: - if mn.startswith(i): - mn = mn[len(i):] - stripped = i - break - else: - stripped = '' - - # we stripped the whole module name - if not mn: - continue - - if fl != mn[0].lower() and mn[0] != '_': - # heading - letter = mn[0].upper() - if letter not in letters: - modindexentries.append(['', False, 0, False, - letter, '', [], False, '']) - letters.append(letter) - tn = mn.split('.')[0] - if tn != mn: - # submodule - if pmn == tn: - # first submodule - make parent collapsable - modindexentries[-1][1] = True - num_collapsables += 1 - elif not pmn.startswith(tn): - # submodule without parent in list, add dummy entry - cg += 1 - modindexentries.append([tn, True, cg, False, '', '', - [], False, stripped]) - else: - num_toplevels += 1 - cg += 1 - modindexentries.append([mn, False, cg, (tn != mn), fn, sy, pl, - dep, stripped]) - pmn = mn - fl = mn[0].lower() - platforms = sorted(platforms) - - # apply heuristics when to collapse modindex at page load: - # only collapse if number of toplevel modules is larger than - # number of submodules - collapse = len(modules) - num_toplevels < num_toplevels - - # As some parts of the module names may have been stripped, those - # names have changed, thus it is necessary to sort the entries. - if ignore: - def sorthelper(entry): - name = entry[0] - if name == '': - # heading - name = entry[4] - return name.lower() - - modindexentries.sort(key=sorthelper) - letters.sort() - - modindexcontext = dict( - modindexentries = modindexentries, - platforms = platforms, - letters = letters, - collapse_modindex = collapse, - ) - self.info(' modindex', nonl=1) - self.handle_page('modindex', modindexcontext, 'modindex.html') + def write_domain_indices(self): + for index in self.domain_indices: + content, collapse = self.env.domains[index[0]].get_index(index[1]) + indexcontext = dict( + indextitle = index[2], + content = content, + collapse_index = collapse, + ) + indexname = '%s-%s' % index[0:2] + self.info(' ' + indexname, nonl=1) + self.handle_page(indexname, indexcontext, 'domainindex.html') def copy_image_files(self): # copy image files diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py index b7adc638..9bbe0a5d 100644 --- a/sphinx/builders/htmlhelp.py +++ b/sphinx/builders/htmlhelp.py @@ -217,9 +217,9 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder): # special books f.write('<LI> ' + object_sitemap % (self.config.html_short_title, 'index.html')) - if self.config.html_use_modindex: - f.write('<LI> ' + object_sitemap % (_('Global Module Index'), - 'modindex.html')) + for index in self.domain_indices: + f.write('<LI> ' + object_sitemap % (index[2], + '%s-%s.html' % index[0:2])) # the TOC tocdoc = self.env.get_and_resolve_doctree( self.config.master_doc, self, prune_toctrees=False) diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py index 623a5c95..72708803 100644 --- a/sphinx/builders/qthelp.py +++ b/sphinx/builders/qthelp.py @@ -130,9 +130,9 @@ class QtHelpBuilder(StandaloneHTMLBuilder): for node in tocdoc.traverse(istoctree): sections.extend(self.write_toc(node)) - if self.config.html_use_modindex: - item = section_template % {'title': _('Global Module Index'), - 'ref': 'modindex.html'} + for index in self.domain_indices: + item = section_template % {'title': index[2], + 'ref': '%s-%s.html' % index[0:2]} sections.append(' '*4*4 + item) sections = '\n'.join(sections) diff --git a/sphinx/config.py b/sphinx/config.py index f6f506bc..1c262eb1 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -81,7 +81,8 @@ class Config(object): html_translator_class = (None, 'html'), html_sidebars = ({}, 'html'), html_additional_pages = ({}, 'html'), - html_use_modindex = (True, 'html'), + html_use_modindex = (True, 'html'), # deprecated + html_domain_indices = (True, 'html'), html_add_permalinks = (True, 'html'), html_use_index = (True, 'html'), html_split_index = (False, 'html'), @@ -125,7 +126,8 @@ class Config(object): latex_logo = (None, None), latex_appendices = ([], None), latex_use_parts = (False, None), - latex_use_modindex = (True, None), + latex_use_modindex = (True, None), # deprecated + latex_domain_indices = (True, None), # paper_size and font_size are still separate values # so that you can give them easily on the command line latex_paper_size = ('letter', None), diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 3f1257ba..e5d3b06f 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -70,6 +70,8 @@ class Domain(object): directives = {} #: role name -> role callable roles = {} + #: (index identifier, localized index name, localized short name) tuples + indices = [] #: data value for a fresh environment initial_data = {} @@ -175,6 +177,22 @@ class Domain(object): """ return [] + def has_index_entries(self, name, docnames=None): + """ + Return True if there are entries for the index given by *name*. If + *docnames* is given, restrict to entries referring to these docnames. + """ + return False + + def get_index(self, name, docnames=None): + """ + Return entries for the index given by *name*. If *docnames* is given, + restrict to entries referring to these docnames. + + XXX document return format + """ + return [], False + from sphinx.domains.c import CDomain from sphinx.domains.std import StandardDomain diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index c1619200..995914c1 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -462,6 +462,9 @@ class PythonDomain(Domain): 'objects': {}, # fullname -> docname, objtype 'modules': {}, # modname -> docname, synopsis, platform, deprecated } + indices = [ + ('modindex', l_('Global Module Index'), l_('modules')), + ] def clear_doc(self, docname): for fullname, (fn, _) in self.data['objects'].items(): @@ -545,3 +548,80 @@ class PythonDomain(Domain): yield (modname, 'module', info[0], 'module-' + modname, 0) for refname, (docname, type) in self.data['objects'].iteritems(): yield (refname, type, docname, refname, 1) + + def has_index_entries(self, name, docnames=None): + if name != 'modindex': + return False + if not docnames: + return bool(self.data['modules']) + else: + for modname, info in self.data['modules'].iteritems(): + if info[0] in docnames: + return True + return False + + def get_index(self, name, docnames=None): + if name != 'modindex': + return None, None + + content = {} + # list of prefixes to ignore + ignores = self.env.config['modindex_common_prefix'] + ignores = sorted(ignores, key=len, reverse=True) + # list of all modules, sorted by module name + modules = sorted(self.data['modules'].iteritems(), + key=lambda x: x[0].lower()) + # sort out collapsable modules + prev_modname = '' + num_toplevels = 0 + current_group = 0 # collapse group + for modname, (docname, synopsis, platforms, deprecated) in modules: + if docnames and docname not in docnames: + continue + + for ignore in ignores: + if modname.startswith(ignore): + modname = modname[len(ignore):] + stripped = ignore + break + else: + stripped = '' + + # we stripped the whole module name? + if not modname: + modname, stripped = stripped, '' + + entries = content.setdefault(modname[0].lower(), []) + + package = modname.split('.')[0] + if package != modname: + # it's a submodule + if prev_modname == package: + # first submodule - make parent a group head + entries[-1][1] = 1 + elif not prev_modname.startswith(package): + # submodule without parent in list, add dummy entry + current_group += 1 + entries.append([stripped + package, 1, current_group, + '', '', '', '', '']) + grouptype = 2 + else: + num_toplevels += 1 + current_group += 1 + grouptype = 0 + + qualifier = deprecated and _('Deprecated') or '' + entries.append([stripped + modname, grouptype, current_group, + docname, 'module-' + stripped + modname, + platforms, qualifier, synopsis]) + prev_modname = modname + + # apply heuristics when to collapse modindex at page load: + # only collapse if number of toplevel modules is larger than + # number of submodules + collapse = len(modules) - num_toplevels < num_toplevels + + # sort by first letter + content = sorted(content.iteritems()) + + return content, collapse diff --git a/sphinx/environment.py b/sphinx/environment.py index d8f1f9fd..c35d0e59 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -110,6 +110,8 @@ class DefaultSubstitutions(Transform): class MoveModuleTargets(Transform): """ Move module targets to their nearest enclosing section title. + + XXX Python specific """ default_priority = 210 @@ -318,11 +320,13 @@ class BuildEnvironment: self.temp_data = {} # Some magically present labels - def add_magic_label(name, description): - self.labels[name] = (name, '', description) - self.anonlabels[name] = (name, '') + def add_magic_label(name, description, target=None): + self.labels[name] = (target or name, '', description) + self.anonlabels[name] = (target or name, '') add_magic_label('genindex', _('Index')) - add_magic_label('modindex', _('Module Index')) + # XXX add per domain? + # compatibility alias + add_magic_label('modindex', _('Module Index'), 'py-modindex') add_magic_label('search', _('Search Page')) def set_warnfunc(self, func): diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 73fb968d..daa88c36 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -164,7 +164,7 @@ html_static_path = ['%(dot)sstatic'] #html_additional_pages = {} # If false, no module index is generated. -#html_use_modindex = True +#html_domain_indices = True # If false, no index is generated. #html_use_index = True @@ -223,7 +223,7 @@ latex_documents = [ #latex_appendices = [] # If false, no module index is generated. -#latex_use_modindex = True +#latex_domain_indices = True # -- Options for Epub output --------------------------------------------------- diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile index 5c0d5018..d5a73f5b 100644 --- a/sphinx/texinputs/Makefile +++ b/sphinx/texinputs/Makefile @@ -37,7 +37,6 @@ bz2: tar latex $(LATEXOPTS) '$<' latex $(LATEXOPTS) '$<' -makeindex -s python.ist '$(basename $<).idx' - -makeindex -s python.ist '$(basename mod$<).idx' latex $(LATEXOPTS) '$<' latex $(LATEXOPTS) '$<' @@ -46,7 +45,6 @@ bz2: tar pdflatex $(LATEXOPTS) '$<' pdflatex $(LATEXOPTS) '$<' -makeindex -s python.ist '$(basename $<).idx' - -makeindex -s python.ist '$(basename mod$<).idx' pdflatex $(LATEXOPTS) '$<' pdflatex $(LATEXOPTS) '$<' diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index dab48b96..a0c14cb4 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -130,8 +130,6 @@ \newcommand{\samp}[1]{`\code{#1}'} \newcommand{\email}[1]{\textsf{#1}} -\newcommand{\py@modulebadkey}{{--just-some-junk--}} - % Redefine the Verbatim environment to allow border and background colors. % The original environment is still used for verbatims within tables. \let\OriginalVerbatim=\Verbatim @@ -193,89 +191,12 @@ \index{#4!#1 #2 #3} } - -% Support for the module index. -% -\newif\ifpy@UseModuleIndex -\py@UseModuleIndexfalse - -\newcommand{\makemodindex}{ - \newwrite\modindexfile - \openout\modindexfile=mod\jobname.idx - \py@UseModuleIndextrue -} - -\newcommand{\printmodindex}{ - \@input@{mod\jobname.ind} -} - -% Add the defining entry for a module. -\newcommand{\py@modindex}[2]{% - \renewcommand{\py@thismodule}{#1} - \ifpy@UseModuleIndex% - \@ifundefined{py@modplat@\py@thismodulekey}{ - \write\modindexfile{\protect\indexentry{#1@{\texttt{#1}}|hyperpage}{\thepage}}% - }{\write\modindexfile{\protect\indexentry{#1@{\texttt{#1 }% - \emph{(\platformof{\py@thismodulekey})}}|hyperpage}{\thepage}}% - } - \fi% -} - -% "Current" keys -\newcommand{\py@thismodule}{} -\newcommand{\py@thismodulekey}{} -\newcommand{\py@thismoduletype}{} -\newcommand{\py@emptymodule}{} - -% \declaremodule[key]{type}{name} -\newcommand{\declaremodule}[3][\py@modulebadkey]{ - \renewcommand{\py@thismoduletype}{#2} - \ifx\py@modulebadkey#1 - \renewcommand{\py@thismodulekey}{#3} - \else - \renewcommand{\py@thismodulekey}{#1} - \fi - \py@modindex{#3}{} - %\label{module-\py@thismodulekey} -} - -% Record module platforms for the Module Index. -\newif\ifpy@ModPlatformFileIsOpen \py@ModPlatformFileIsOpenfalse -\long\def\py@writeModPlatformFile#1{% - \protected@write\py@ModPlatformFile% - {\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}% - {\string#1}% -} -\newcommand{\py@ModPlatformFilename}{\jobname.pla} -\newcommand{\platform}[1]{ - \ifpy@ModPlatformFileIsOpen\else - \newwrite\py@ModPlatformFile - \openout\py@ModPlatformFile=\py@ModPlatformFilename - \py@ModPlatformFileIsOpentrue - \fi - \py@writeModPlatformFile{\py@defplatform{\py@thismodulekey}{#1}} -} -\newcommand{\py@defplatform}[2]{\expandafter\def\csname py@modplat@#1\endcsname{#2}} -\newcommand{\platformof}[1]{\csname py@modplat@#1\endcsname} - -\InputIfFileExists{\jobname.pla}{}{} - % \moduleauthor{name}{email} \newcommand{\moduleauthor}[2]{} % \sectionauthor{name}{email} \newcommand{\sectionauthor}[2]{} -% Ignore module synopsis. -\newcommand{\modulesynopsis}[1]{} - -% Reset "current" objects. -\newcommand{\resetcurrentobjects}{ - \renewcommand{\py@thismodule}{} - \renewcommand{\py@thismodulekey}{} - \renewcommand{\py@thismoduletype}{} -} - % Augment the sectioning commands used to get our own font family in place, % and reset some internal data items: \titleformat{\section}{\Large\py@HeaderFamily}% @@ -301,8 +222,6 @@ \let\makelabel=\py@itemnewline} }{\end{list}} -\let\py@badkey=\@undefined - % \optional is used for ``[, arg]``, i.e. desc_optional nodes. \newcommand{\optional}[1]{% {\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}} @@ -325,7 +244,7 @@ % the example completely. % \newcommand{\grammartoken}[1]{\texttt{#1}} -\newenvironment{productionlist}[1][\py@badkey]{ +\newenvironment{productionlist}[1][\@undefined]{ \def\optional##1{{\Large[}##1{\Large]}} \def\production##1##2{\hypertarget{grammar-token-##1}{}% \code{##1}&::=&\code{##2}\\} diff --git a/sphinx/themes/basic/domainindex.html b/sphinx/themes/basic/domainindex.html new file mode 100644 index 00000000..9f4d4637 --- /dev/null +++ b/sphinx/themes/basic/domainindex.html @@ -0,0 +1,54 @@ +{# + basic/domainindex.html + ~~~~~~~~~~~~~~~~~~~~~~ + + Template for domain indices (module index, ...). + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{% extends "layout.html" %} +{% set title = indextitle %} +{% block extrahead %} +{{ super() }} +{% if not embedded and collapse_index %} + <script type="text/javascript"> + DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true; + </script> +{% endif %} +{% endblock %} +{% block body %} + + <h1>{{ indextitle }}</h1> + + <div class="modindex-jumpbox"> + {%- for (letter, entries) in content %} + <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a> + {%- if not loop.last %} | {% endif %} + {%- endfor %} + </div> + + <table class="indextable modindextable" cellspacing="0" cellpadding="2"> + {%- for letter, entries in content %} + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap"><td></td><td><a name="cap-{{ letter }}"> + <strong>{{ letter }}</strong></a></td><td></td></tr> + {%- for (name, grouptype, group, page, anchor, extra, qualifier, description) + in entries %} + <tr{% if grouptype == 2 %} class="cg-{{ cgroup }}"{% endif %}> + <td>{% if grouptype == 1 -%} + <img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ group }}" + class="toggler" style="display: none" alt="-" /> + {%- endif %}</td> + <td>{% if grouptype == 2 %} {% endif %} + {% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%} + <tt class="xref">{{ name|e }}</tt> + {%- if page %}</a>{% endif %} + {%- if extra %} <em>({{ extra|e }})</em>{% endif -%} + </td><td>{% if qualifier %}<strong>{{ qualifier|e }}:</strong>{% endif %} + <em>{{ description|e }}</em></td></tr> + {%- endfor %} + {%- endfor %} + </table> + +{% endblock %} diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index d3ef88ab..c844dabc 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -98,7 +98,7 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: '{{ pathto("", 1) }}', VERSION: '{{ release|e }}', - COLLAPSE_MODINDEX: false, + COLLAPSE_INDEX: false, FILE_SUFFIX: '{{ file_suffix }}', HAS_SOURCE: {{ has_source|lower }} }; diff --git a/sphinx/themes/basic/modindex.html b/sphinx/themes/basic/modindex.html deleted file mode 100644 index 96f8ac43..00000000 --- a/sphinx/themes/basic/modindex.html +++ /dev/null @@ -1,52 +0,0 @@ -{# - basic/modindex.html - ~~~~~~~~~~~~~~~~~~~ - - Template for the module index. - - :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -#} -{% extends "layout.html" %} -{% set title = _('Global Module Index') %} -{% block extrahead %} -{{ super() }} -{% if not embedded and collapse_modindex %} - <script type="text/javascript"> - DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX = true; - </script> -{% endif %} -{% endblock %} -{% block body %} - - <h1 id="global-module-index">{{ _('Global Module Index') }}</h1> - - <div class="modindex-jumpbox"> - {%- for letter in letters %} - <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a> {% if not loop.last %}| {% endif %} - {%- endfor %} - </div> - - <table class="indextable modindextable" cellspacing="0" cellpadding="2"> - {%- for modname, collapse, cgroup, indent, fname, synops, pform, dep, stripped in modindexentries %} - {%- if not modname -%} - <tr class="pcap"><td></td><td> </td><td></td></tr> - <tr class="cap"><td></td><td><a name="cap-{{ fname }}"><strong>{{ fname }}</strong></a></td><td></td></tr> - {%- else -%} - <tr{% if indent %} class="cg-{{ cgroup }}"{% endif %}> - <td>{% if collapse -%} - <img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ cgroup }}" - class="toggler" style="display: none" alt="-" /> - {%- endif %}</td> - <td>{% if indent %} {% endif %} - {% if fname %}<a href="{{ fname }}">{% endif -%} - <tt class="xref">{{ stripped|e }}{{ modname|e }}</tt> - {%- if fname %}</a>{% endif %} - {%- if pform and pform[0] %} <em>({{ pform|join(', ') }})</em>{% endif -%} - </td><td>{% if dep %}<strong>{{ _('Deprecated')}}:</strong>{% endif %} - <em>{{ synops|e }}</em></td></tr> - {%- endif -%} - {% endfor %} - </table> - -{% endblock %} diff --git a/sphinx/themes/basic/static/doctools.js b/sphinx/themes/basic/static/doctools.js index e91c4f3e..28c7a6da 100644 --- a/sphinx/themes/basic/static/doctools.js +++ b/sphinx/themes/basic/static/doctools.js @@ -111,7 +111,7 @@ var Documentation = { init : function() { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); - this.initModIndex(); + this.initIndexTable(); }, /** @@ -192,9 +192,9 @@ var Documentation = { }, /** - * init the modindex toggle buttons + * init the domain index toggle buttons */ - initModIndex : function() { + initIndexTable : function() { var togglers = $('img.toggler').click(function() { var src = $(this).attr('src'); var idnum = $(this).attr('id').substr(7); @@ -204,7 +204,7 @@ var Documentation = { else $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX) { + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { togglers.click(); } }, diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py index 73790829..4cabd9b2 100644 --- a/sphinx/util/texescape.py +++ b/sphinx/util/texescape.py @@ -99,6 +99,7 @@ tex_replacements = [ ] tex_escape_map = {} +tex_replace_map = {} tex_hl_escape_map_old = {} # replacement map for Pygments <= 1.1 tex_hl_escape_map_new = {} # replacement map for Pygments >= 1.2 _old_cmd_chars = {ord(u'\\'): u'@', ord(u'{'): u'[', ord(u'}'): u']'} @@ -106,6 +107,7 @@ _old_cmd_chars = {ord(u'\\'): u'@', ord(u'{'): u'[', ord(u'}'): u']'} def init(): for a, b in tex_replacements: tex_escape_map[ord(a)] = b + tex_replace_map[ord(a)] = u'_' for a, b in tex_replacements: if a in u'[]{}\\': continue diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 74d2c8d2..c75424b2 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -24,7 +24,7 @@ from sphinx import highlighting from sphinx.errors import SphinxError from sphinx.locale import admonitionlabels, versionlabels, _ from sphinx.util.osutil import ustrftime -from sphinx.util.texescape import tex_escape_map +from sphinx.util.texescape import tex_escape_map, tex_replace_map from sphinx.util.smartypants import educateQuotesLatex HEADER = r'''%% Generated by Sphinx. @@ -47,7 +47,6 @@ HEADER = r'''%% Generated by Sphinx. \newcommand{\sphinxlogo}{%(logo)s} \renewcommand{\releasename}{%(releasename)s} %(makeindex)s -%(makemodindex)s ''' BEGIN_DOC = r''' @@ -58,9 +57,6 @@ BEGIN_DOC = r''' ''' FOOTER = r''' -%(footer)s -\renewcommand{\indexname}{%(modindexname)s} -%(printmodindex)s \renewcommand{\indexname}{%(indexname)s} %(printindex)s \end{document} @@ -146,12 +142,10 @@ class LaTeXTranslator(nodes.NodeVisitor): 'logo': '', 'releasename': 'Release', 'makeindex': '\\makeindex', - 'makemodindex': '\\makemodindex', 'shorthandoff': '', 'maketitle': '\\maketitle', 'tableofcontents': '\\tableofcontents', 'footer': '', - 'printmodindex': '\\printmodindex', 'printindex': '\\printindex', } @@ -176,7 +170,6 @@ class LaTeXTranslator(nodes.NodeVisitor): 'author': document.settings.author, 'releasename': _('Release'), 'preamble': builder.config.latex_preamble, - 'modindexname': _('Module Index'), 'indexname': _('Index'), }) if document.settings.docclass == 'howto': @@ -204,9 +197,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.elements['fncychap'] = '\\usepackage[Sonny]{fncychap}' else: self.elements['classoptions'] += ',english' - if not builder.config.latex_use_modindex: - self.elements['makemodindex'] = '' - self.elements['printmodindex'] = '' # allow the user to override them all self.elements.update(builder.config.latex_elements) @@ -243,11 +233,60 @@ class LaTeXTranslator(nodes.NodeVisitor): self.first_param = 0 def astext(self): - return (HEADER % self.elements + self.highlighter.get_stylesheet() + - u''.join(self.body) + FOOTER % self.elements) + return (HEADER % self.elements + + self.highlighter.get_stylesheet() + + u''.join(self.body) + + '\n' + self.elements['footer'] + '\n' + + self.generate_indices() + + FOOTER % self.elements) + + def hypertarget(self, target, text='', anchor=True): + #return '\\hypertarget{%s}{%s}' % (self.idescape(target), text) + return (anchor and '\\phantomsection' or '') + \ + '\\label{%s}%s' % (self.idescape(target), text) + + def hyperlink(self, target): + #return '\\hyperlink{%s}{' % (self.idescape(target)) + return '\\hyperref[%s]{' % (self.idescape(target)) def idescape(self, id): - return str(unicode(id).translate(tex_escape_map)) + return str(unicode(id).translate(tex_replace_map)) + + def generate_indices(self): + def generate(content, collapsed): + ret.append('\\begin{theindex}\n') + ret.append('\\def\\bigletter#1{{\\Large\\sffamily#1}' + '\\nopagebreak\\vspace{1mm}}\n') + for i, (letter, entries) in enumerate(content): + if i > 0: + ret.append('\\indexspace\n') + ret.append('\\bigletter{%s}\n' % letter) + for entry in entries: + if not entry[4]: + continue + ret.append('\\item {\\texttt{%s}}, \\pageref{%s}' % + (self.encode(entry[0]), entry[4])) + ret.append('\\end{theindex}\n') + + ret = [] + # latex_domain_indices can be False/True or a list of index names + indices_config = self.builder.config.latex_domain_indices + if indices_config: + for domain in self.builder.env.domains.itervalues(): + for indexinfo in domain.indices: + indexname = '%s-%s' % (domain.name, indexinfo[0]) + if isinstance(indices_config, list): + if indexname not in indices_config: + continue + if not domain.has_index_entries(indexinfo[0], + self.builder.docnames): + continue + ret.append('\\renewcommand{\\indexname}{%s}\n' % + indexinfo[1]) + generate(*domain.get_index(indexinfo[0], + self.builder.docnames)) + + return ''.join(ret) def visit_document(self, node): self.footnotestack.append(self.collect_footnotes(node)) @@ -261,8 +300,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append('\n\\appendix\n') self.first_document = -1 if node.has_key('docname'): - self.body.append('\\hypertarget{--doc-%s}{}' % - self.idescape(node['docname'])) + self.body.append(self.hypertarget('--doc-' + node['docname'])) # "- 1" because the level is increased before the title is visited self.sectionlevel = self.top_sectionlevel - 1 def depart_document(self, node): @@ -275,21 +313,17 @@ class LaTeXTranslator(nodes.NodeVisitor): for bi in self.bibitems: # cite_key: underscores must not be escaped cite_key = bi[0].replace(r"\_", "_") - self.body.append('\\bibitem[%s]{%s}{\hypertarget{%s}{} %s}\n' % + self.body.append('\\bibitem[%s]{%s}{%s %s}\n' % (bi[0], cite_key, - self.idescape(cite_key.lower()), bi[1])) + self.hypertarget(cite_key.lower()), bi[1])) self.body.append('\\end{thebibliography}\n') self.bibitems = [] def visit_start_of_file(self, node): - # This marks the begin of a new file; therefore the current module and - # class must be reset - self.body.append('\n\\resetcurrentobjects\n') - # and also, new footnotes + # collect new footnotes self.footnotestack.append(self.collect_footnotes(node)) # also add a document target - self.body.append('\\hypertarget{--doc-%s}{}' % - self.idescape(node['docname'])) + self.body.append(self.hypertarget('--doc-' + node['docname'])) self.curfilestack.append(node['docname']) def collect_footnotes(self, node): @@ -321,14 +355,10 @@ class LaTeXTranslator(nodes.NodeVisitor): if not self.this_is_the_title: self.sectionlevel += 1 self.body.append('\n\n') - if self.next_section_target: - self.body.append(r'\hypertarget{%s}{}' % - self.idescape(self.next_section_target)) - self.next_section_target = None #if node.get('ids'): # for id in node['ids']: # if id not in self.written_ids: - # self.body.append(r'\hypertarget{%s}{}' % id) + # self.body.append(self.hypertarget(id)) # self.written_ids.add(id) def depart_section(self, node): self.sectionlevel = max(self.sectionlevel - 1, @@ -400,6 +430,12 @@ class LaTeXTranslator(nodes.NodeVisitor): # just use "subparagraph", it's not numbered anyway self.body.append(r'\%s{' % self.sectionnames[-1]) self.context.append('}\n') + + if self.next_section_target: + self.context[-1] += self.hypertarget(self.next_section_target, + anchor=False) + self.next_section_target = None + elif isinstance(parent, (nodes.topic, nodes.sidebar)): self.body.append(r'\textbf{') self.context.append('}\n\n\medskip\n\n') @@ -438,7 +474,7 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_signature(self, node): if node.parent['objtype'] != 'describe' and node['ids']: - hyper = '\\hypertarget{%s}{}' % self.idescape(node['ids'][0]) + hyper = self.hypertarget(node['ids'][0]) else: hyper = '' self.body.append(hyper) @@ -700,7 +736,7 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_term(self, node): ctx = '] \\leavevmode' if node.has_key('ids') and node['ids']: - ctx += '\\hypertarget{%s}{}' % self.idescape(node['ids'][0]) + ctx += self.hypertarget(node['ids'][0]) self.body.append('\\item[') self.context.append(ctx) def depart_term(self, node): @@ -759,14 +795,14 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_module(self, node): modname = node['modname'] - self.body.append('\n\\hypertarget{module-%s}{}' % - self.idescape(modname.replace(' ',''))) - self.body.append('\n\\declaremodule[%s]{}{%s}' % ( - modname.replace('_', ''), self.encode(modname))) - self.body.append('\n\\modulesynopsis{%s}' % - self.encode(node['synopsis'])) - if node.has_key('platform'): - self.body.append('\\platform{%s}' % self.encode(node['platform'])) + self.body.append('\n' + + self.hypertarget('module-' + modname.replace(' ',''))) + #self.body.append('\n\\declaremodule[%s]{}{%s}' % ( + # modname.replace('_', ''), self.encode(modname))) + #self.body.append('\n\\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 @@ -925,7 +961,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # indexing uses standard LaTeX index markup, so the targets # will be generated differently if not id.startswith('index-'): - self.body.append(r'\hypertarget{%s}{}' % self.idescape(id)) + self.body.append(self.hypertarget(id)) if node.has_key('refid') and node['refid'] not in self.written_ids: parindex = node.parent.index(node) @@ -986,14 +1022,14 @@ class LaTeXTranslator(nodes.NodeVisitor): self.context.append('}') elif uri.startswith('#'): # references to labels - self.body.append('\\hyperlink{%s}{' % self.idescape(uri[1:])) + self.body.append(self.hyperlink(uri[1:])) self.context.append('}') elif uri.startswith('%'): # references to documents or labels inside documents hashindex = uri.find('#') targetname = (hashindex == -1) and '--doc-' + uri[1:] \ or uri[hashindex+1:] - self.body.append('\\hyperlink{%s}{' % self.idescape(targetname)) + self.body.append(self.hyperlink(targetname)) self.context.append('}') elif uri.startswith('@token'): if self.in_production_list: |
