Commits

Georg Brandl  committed dbe4e1c

Added a toctree variable to the templates, and the ability to
include external links in toctrees.

Patch by Stefan Seefeld.

  • Participants
  • Parent commits 5834024

Comments (0)

Files changed (7)

 * Dave Kuhlman -- original LaTeX writer
 * Thomas Lamb -- linkcheck builder
 * Benjamin Peterson -- unittests
+* Stefan Seefeld -- toctree improvements
 * Antonio Valentino -- qthelp builder
 * Pauli Virtanen -- autodoc improvements
 * Sebastian Wiesner -- image handling, distutils support
   - #23: Added a ``classmethod`` directive along with ``method``
     and ``staticmethod``.
 
+  - Added a toctree variable to the templates, and the ability to
+    include external links in toctrees.
+
 * Configuration:
 
   - The new ``html_add_permalinks`` config value can be used to

File doc/concepts.rst

    The second line above will link to the ``strings`` document, but will use the
    title "All about strings" instead of the title of the ``strings`` document.
 
+   You can also add external links, by giving an HTTP URL instead of a document
+   name.
+
    You can use "globbing" in toctree directives, by giving the ``glob`` flag
    option.  All entries are then matched against the list of available
    documents, and matches are inserted into the list alphabetically.  Example::
       Added "globbing" option.
 
    .. versionchanged:: 0.6
-      Added "hidden" option.
+      Added "hidden" option and external links.
 
 
 Special names

File doc/templating.rst

 
 .. data:: builder
 
-   The name of the builder (for builtin builders, ``html``, ``htmlhelp``, or
-   ``web``).
+   The name of the builder (e.g. ``html`` or ``htmlhelp``).
+
+.. data:: embedded
+
+   True if the built HTML is supposed to be embedded in some application that
+   handles navigation, e.g. HTML Help or Qt Help.
 
 .. data:: next
 
 .. data:: prev
 
    Like :data:`next`, but for the previous page.
+
+
+In documents that are created from source files (as opposed to
+automatically-generated files like the module index, or documents that already
+are in HTML form), these variables are also available:
+
+.. data:: toc
+
+   The local table of contents for the current page, rendered as HTML bullet
+   lists.
+
+.. data:: toctree
+
+   The global TOC tree containing the current page, rendered as HTML bullet
+   lists.

File sphinx/builders/html.py

             metatags = metatags,
             rellinks = rellinks,
             sourcename = sourcename,
+            toctree = self.render_partial(self.env.get_toctree_for(
+                                          docname, self))['fragment'],
             toc = self.render_partial(self.env.get_toc_for(docname))['fragment'],
             # only display a TOC if there's more than one item to show
             display_toc = (self.env.toc_num_entries[docname] > 1),

File sphinx/directives/other.py

     glob = 'glob' in options
 
     ret = []
+    # (title, ref) pairs, where ref may be a document, or an external link,
+    # and title may be None if the document's title is to be used
+    entries = []
     includefiles = []
     includetitles = {}
     all_docnames = env.found_docs.copy()
             # look for explicit titles and documents ("Some Title <document>").
             m = caption_ref_re.match(entry)
             if m:
-                docname = m.group(2)
-                includetitles[docname] = m.group(1)
+                ref = m.group(2)
+                title = m.group(1)
+                docname = ref
             else:
-                docname = entry
+                ref = docname = entry
+                title = None
             # remove suffixes (backwards compatibility)
             if docname.endswith(suffix):
                 docname = docname[:-len(suffix)]
             # absolutize filenames
             docname = docname_join(env.docname, docname)
-            if docname not in env.found_docs:
+            if ref.startswith('http://'): # FIXME: generalize to arbitrary xrefs
+                entries.append((title, ref))
+            elif docname not in env.found_docs:
                 ret.append(state.document.reporter.warning(
                     'toctree references unknown document %r' % docname, line=lineno))
             else:
+                entries.append((title, ref))
                 includefiles.append(docname)
         else:
             patname = docname_join(env.docname, entry)
             docnames = sorted(patfilter(all_docnames, patname))
             for docname in docnames:
                 all_docnames.remove(docname) # don't include it again
+                entries.append((None, docname))
                 includefiles.append(docname)
             if not docnames:
                 ret.append(state.document.reporter.warning(
                     'toctree glob pattern %r didn\'t match any documents' % entry,
                     line=lineno))
     subnode = addnodes.toctree()
+    subnode['entries'] = entries
     subnode['includefiles'] = includefiles
-    subnode['includetitles'] = includetitles
     subnode['maxdepth'] = options.get('maxdepth', -1)
     subnode['glob'] = glob
     subnode['hidden'] = 'hidden' in options

File sphinx/environment.py

             node['refuri'] = node['anchorname']
         return toc
 
+    def get_toctree_for(self, docname, builder):
+        """Return the global TOC nodetree."""
+
+        # XXX why master_doc?
+        doctree = self.get_doctree(self.config.master_doc)
+        for toctreenode in doctree.traverse(addnodes.toctree):
+            result = self.resolve_toctree(docname, builder, toctreenode,
+                                          prune=True)
+            if result is not None:
+                return result
+
     # -------
     # these are called from docutils directives and therefore use self.docname
     #
         if toctree.get('hidden', False):
             return None
 
-        def _walk_depth(node, depth, maxdepth, titleoverrides):
+        def _walk_depth(node, depth, maxdepth):
             """Utility: Cut a TOC at a specified depth."""
             for subnode in node.children[:]:
                 if isinstance(subnode, (addnodes.compact_paragraph, nodes.list_item)):
                     subnode['classes'].append('toctree-l%d' % (depth-1))
-                    _walk_depth(subnode, depth, maxdepth, titleoverrides)
+                    _walk_depth(subnode, depth, maxdepth)
                 elif isinstance(subnode, nodes.bullet_list):
                     if maxdepth > 0 and depth > maxdepth:
                         subnode.parent.replace(subnode, [])
                     else:
-                        _walk_depth(subnode, depth+1, maxdepth, titleoverrides)
+                        _walk_depth(subnode, depth+1, maxdepth)
 
         def _entries_from_toctree(toctreenode, separate=False, subtree=False):
             """Return TOC entries for a toctree node."""
-            includefiles = map(str, toctreenode['includefiles'])
-
+            refs = [(e[0], str(e[1])) for e in toctreenode['entries']]
             entries = []
-            for includefile in includefiles:
+            for (title, ref) in refs:
                 try:
-                    toc = self.tocs[includefile].deepcopy()
+                    if ref.startswith('http://'): # FIXME: (see directives/other.py)
+                        reference = nodes.reference('', '', refuri=ref, anchorname='',
+                                                    *[nodes.Text(title)])
+                        para = addnodes.compact_paragraph('', '', reference)
+                        item = nodes.list_item('', para)
+                        toc = nodes.bullet_list('', item)
+                    else:
+                        toc = self.tocs[ref].deepcopy()
+                        if title and toc.children and len(toc.children) == 1:
+                            for refnode in toc.children[0].traverse(nodes.reference):
+                                if refnode['refuri'] == ref and not refnode['anchorname']:
+                                    refnode.children = [nodes.Text(title)]
                     if not toc.children:
                         # empty toc means: no titles will show up in the toctree
                         self.warn(docname, 'toctree contains reference to document '
                                   '%r that doesn\'t have a title: no link will be '
-                                  'generated' % includefile)
+                                  'generated' % ref)
+
                 except KeyError:
                     # this is raised if the included file does not exist
                     self.warn(docname, 'toctree contains reference to nonexisting '
-                              'document %r' % includefile)
+                              'document %r' % ref)
                 else:
                     # if titles_only is given, only keep the main title and
                     # sub-toctrees
             return entries
 
         maxdepth = maxdepth or toctree.get('maxdepth', -1)
-        titleoverrides = toctree.get('includetitles', {})
 
         # NOTE: previously, this was separate=True, but that leads to artificial
         # separation when two or more toctree entries form a logical unit, so
         newnode = addnodes.compact_paragraph('', '', *tocentries)
         newnode['toctree'] = True
         # prune the tree to maxdepth and replace titles, also set level classes
-        _walk_depth(newnode, 1, prune and maxdepth or 0, titleoverrides)
-        # replace titles, if needed, and set the target paths in the
-        # toctrees (they are not known at TOC generation time)
+        _walk_depth(newnode, 1, prune and maxdepth or 0)
+        # set the target paths in the toctrees (they are not known at TOC generation time)
         for refnode in newnode.traverse(nodes.reference):
-            if titleoverrides and not refnode['anchorname'] \
-                   and refnode['refuri'] in titleoverrides:
-                newtitle = titleoverrides[refnode['refuri']]
-                refnode.children = [nodes.Text(newtitle)]
             refnode['refuri'] = builder.get_relative_uri(
                 docname, refnode['refuri']) + refnode['anchorname']
         return newnode