mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add globbing-style toctree entries.
This commit is contained in:
parent
407a0c47c1
commit
548cdc858a
6
CHANGES
6
CHANGES
@ -4,9 +4,11 @@ Changes in trunk
|
|||||||
New features added
|
New features added
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
* The ``toctree`` directive now supports a ``glob`` option that allows
|
||||||
|
glob-style entries in the content.
|
||||||
|
|
||||||
* If the `pygments_style` config value contains a dot it's treated as the
|
* If the `pygments_style` config value contains a dot it's treated as the
|
||||||
import path of a custom Pygments style class.
|
import path of a custom Pygments style class.
|
||||||
* autodoc detects descriptors properly now
|
|
||||||
|
|
||||||
* A new config value, `exclude_dirs`, can be used to exclude whole
|
* A new config value, `exclude_dirs`, can be used to exclude whole
|
||||||
directories from the search for source files.
|
directories from the search for source files.
|
||||||
@ -36,6 +38,8 @@ Bugs fixed
|
|||||||
and index file. Remove two remaining instances of hard-coded
|
and index file. Remove two remaining instances of hard-coded
|
||||||
"documentation".
|
"documentation".
|
||||||
|
|
||||||
|
* sphinx.ext.autodoc: descriptors are detected properly now.
|
||||||
|
|
||||||
* Lots of little fixes to the LaTeX output and style.
|
* Lots of little fixes to the LaTeX output and style.
|
||||||
|
|
||||||
* Fix OpenSearch template and make template URL absolute. The
|
* Fix OpenSearch template and make template URL absolute. The
|
||||||
|
@ -70,18 +70,36 @@ tables of contents. The ``toctree`` directive is the central element.
|
|||||||
|
|
||||||
The second line above will link to the ``strings`` document, but will use the
|
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.
|
title "All about strings" instead of the title of the ``strings`` document.
|
||||||
|
|
||||||
|
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::
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:glob:
|
||||||
|
|
||||||
|
intro*
|
||||||
|
recipe/*
|
||||||
|
*
|
||||||
|
|
||||||
|
This includes first all documents whose names start with ``intro``, then all
|
||||||
|
documents in the ``recipe`` folder, then all remaining documents (except the
|
||||||
|
one containing the directive, of course.) [#]_
|
||||||
|
|
||||||
In the end, all documents in the :term:`source directory` (or subdirectories)
|
In the end, all documents in the :term:`source directory` (or subdirectories)
|
||||||
must occur in some ``toctree`` directive; Sphinx will emit a warning if it
|
must occur in some ``toctree`` directive; Sphinx will emit a warning if it
|
||||||
finds a file that is not included, because that means that this file will not
|
finds a file that is not included, because that means that this file will not
|
||||||
be reachable through standard navigation. Use :confval:`unused_documents` to
|
be reachable through standard navigation. Use :confval:`unused_documents` to
|
||||||
explicitly exclude documents from this check, and :confval:`exclude_dirs` to
|
explicitly exclude documents from building, and :confval:`exclude_dirs` to
|
||||||
exclude whole directories.
|
exclude whole directories.
|
||||||
|
|
||||||
The "master document" (selected by :confval:`master_doc`) is the "root" of
|
The "master document" (selected by :confval:`master_doc`) is the "root" of
|
||||||
the TOC tree hierarchy. It can be used as the documentation's main page, or
|
the TOC tree hierarchy. It can be used as the documentation's main page, or
|
||||||
as a "full table of contents" if you don't give a ``maxdepth`` option.
|
as a "full table of contents" if you don't give a ``maxdepth`` option.
|
||||||
|
|
||||||
|
.. versionchanged:: 0.2.1
|
||||||
|
Added "globbing" option.
|
||||||
|
|
||||||
|
|
||||||
Special names
|
Special names
|
||||||
-------------
|
-------------
|
||||||
@ -110,3 +128,11 @@ The special document names (and pages generated for them) are:
|
|||||||
Though only few such names are currently used by Sphinx, you should not create
|
Though only few such names are currently used by Sphinx, you should not create
|
||||||
documents or document-containing directories with such names. (Using ``_`` as
|
documents or document-containing directories with such names. (Using ``_`` as
|
||||||
a prefix for a custom template directory is fine.)
|
a prefix for a custom template directory is fine.)
|
||||||
|
|
||||||
|
|
||||||
|
.. rubric:: Footnotes
|
||||||
|
|
||||||
|
.. [#] A note on available globbing syntax: you can use the standard shell
|
||||||
|
constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
|
||||||
|
these all don't match slashes. A double star ``**`` can be used to match
|
||||||
|
any sequence of characters *including* slashes.
|
||||||
|
@ -19,6 +19,7 @@ from docutils import nodes
|
|||||||
from docutils.parsers.rst import directives
|
from docutils.parsers.rst import directives
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.util import patfilter
|
||||||
from sphinx.roles import caption_ref_re
|
from sphinx.roles import caption_ref_re
|
||||||
from sphinx.util.compat import make_admonition
|
from sphinx.util.compat import make_admonition
|
||||||
|
|
||||||
@ -650,28 +651,46 @@ def toctree_directive(name, arguments, options, content, lineno,
|
|||||||
env = state.document.settings.env
|
env = state.document.settings.env
|
||||||
suffix = env.config.source_suffix
|
suffix = env.config.source_suffix
|
||||||
dirname = posixpath.dirname(env.docname)
|
dirname = posixpath.dirname(env.docname)
|
||||||
|
glob = 'glob' in options
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
subnode = addnodes.toctree()
|
subnode = addnodes.toctree()
|
||||||
includefiles = []
|
includefiles = []
|
||||||
includetitles = {}
|
includetitles = {}
|
||||||
for docname in content:
|
all_docnames = env.found_docs.copy()
|
||||||
if not docname:
|
# don't add the currently visited file in catch-all patterns
|
||||||
|
all_docnames.remove(env.docname)
|
||||||
|
for entry in content:
|
||||||
|
if not entry:
|
||||||
continue
|
continue
|
||||||
# look for explicit titles and documents ("Some Title <document>").
|
if not glob:
|
||||||
m = caption_ref_re.match(docname)
|
# look for explicit titles and documents ("Some Title <document>").
|
||||||
if m:
|
m = caption_ref_re.match(entry)
|
||||||
docname = m.group(2)
|
if m:
|
||||||
includetitles[docname] = m.group(1)
|
docname = m.group(2)
|
||||||
# absolutize filenames, remove suffixes
|
includetitles[docname] = m.group(1)
|
||||||
if docname.endswith(suffix):
|
else:
|
||||||
docname = docname[:-len(suffix)]
|
docname = entry
|
||||||
docname = posixpath.normpath(posixpath.join(dirname, docname))
|
# remove suffixes (backwards compatibility)
|
||||||
if docname not in env.found_docs:
|
if docname.endswith(suffix):
|
||||||
ret.append(state.document.reporter.warning(
|
docname = docname[:-len(suffix)]
|
||||||
'toctree references unknown document %r' % docname, line=lineno))
|
# absolutize filenames
|
||||||
|
docname = posixpath.normpath(posixpath.join(dirname, docname))
|
||||||
|
if docname not in env.found_docs:
|
||||||
|
ret.append(state.document.reporter.warning(
|
||||||
|
'toctree references unknown document %r' % docname, line=lineno))
|
||||||
|
else:
|
||||||
|
includefiles.append(docname)
|
||||||
else:
|
else:
|
||||||
includefiles.append(docname)
|
patname = posixpath.normpath(posixpath.join(dirname, entry))
|
||||||
|
docnames = sorted(patfilter(all_docnames, patname))
|
||||||
|
for docname in docnames:
|
||||||
|
all_docnames.remove(docname) # don't include it again
|
||||||
|
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['includefiles'] = includefiles
|
subnode['includefiles'] = includefiles
|
||||||
subnode['includetitles'] = includetitles
|
subnode['includetitles'] = includetitles
|
||||||
subnode['maxdepth'] = options.get('maxdepth', -1)
|
subnode['maxdepth'] = options.get('maxdepth', -1)
|
||||||
@ -679,7 +698,7 @@ def toctree_directive(name, arguments, options, content, lineno,
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
toctree_directive.content = 1
|
toctree_directive.content = 1
|
||||||
toctree_directive.options = {'maxdepth': int}
|
toctree_directive.options = {'maxdepth': int, 'glob': directives.flag}
|
||||||
directives.register_directive('toctree', toctree_directive)
|
directives.register_directive('toctree', toctree_directive)
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,6 +242,10 @@ p {
|
|||||||
margin: 0.8em 0 0.5em 0;
|
margin: 0.8em 0 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.rubric {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0.7em 0 0.3em 0;
|
padding: 0.7em 0 0.3em 0;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import tempfile
|
import tempfile
|
||||||
@ -158,7 +159,7 @@ def fmt_ex(ex):
|
|||||||
|
|
||||||
|
|
||||||
def rpartition(s, t):
|
def rpartition(s, t):
|
||||||
"""Similar to str.rpartition from 2.5."""
|
"""Similar to str.rpartition from 2.5, but doesn't return the separator."""
|
||||||
i = s.rfind(t)
|
i = s.rfind(t)
|
||||||
if i != -1:
|
if i != -1:
|
||||||
return s[:i], s[i+len(t):]
|
return s[:i], s[i+len(t):]
|
||||||
@ -187,3 +188,64 @@ def save_traceback():
|
|||||||
os.write(fd, exc)
|
os.write(fd, exc)
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _translate_pattern(pat):
|
||||||
|
"""
|
||||||
|
Translate a shell-style glob pattern to a regular expression.
|
||||||
|
|
||||||
|
Adapted from the fnmatch module, but enhanced so that single stars don't
|
||||||
|
match slashes.
|
||||||
|
"""
|
||||||
|
i, n = 0, len(pat)
|
||||||
|
res = ''
|
||||||
|
while i < n:
|
||||||
|
c = pat[i]
|
||||||
|
i += 1
|
||||||
|
if c == '*':
|
||||||
|
if i < n and pat[i] == '*':
|
||||||
|
# double star matches slashes too
|
||||||
|
i += 1
|
||||||
|
res = res + '.*'
|
||||||
|
else:
|
||||||
|
# single star doesn't match slashes
|
||||||
|
res = res + '[^/]*'
|
||||||
|
elif c == '?':
|
||||||
|
# question mark doesn't match slashes too
|
||||||
|
res = res + '[^/]'
|
||||||
|
elif c == '[':
|
||||||
|
j = i
|
||||||
|
if j < n and pat[j] == '!':
|
||||||
|
j += 1
|
||||||
|
if j < n and pat[j] == ']':
|
||||||
|
j += 1
|
||||||
|
while j < n and pat[j] != ']':
|
||||||
|
j += 1
|
||||||
|
if j >= n:
|
||||||
|
res = res + '\\['
|
||||||
|
else:
|
||||||
|
stuff = pat[i:j].replace('\\', '\\\\')
|
||||||
|
i = j + 1
|
||||||
|
if stuff[0] == '!':
|
||||||
|
# negative pattern mustn't match slashes too
|
||||||
|
stuff = '^/' + stuff[1:]
|
||||||
|
elif stuff[0] == '^':
|
||||||
|
stuff = '\\' + stuff
|
||||||
|
res = '%s[%s]' % (res, stuff)
|
||||||
|
else:
|
||||||
|
res += re.escape(c)
|
||||||
|
return res + '$'
|
||||||
|
|
||||||
|
|
||||||
|
_pat_cache = {}
|
||||||
|
|
||||||
|
def patfilter(names, pat):
|
||||||
|
"""
|
||||||
|
Return the subset of the list NAMES that match PAT.
|
||||||
|
Adapted from fnmatch module.
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
if not pat in _pat_cache:
|
||||||
|
_pat_cache[pat] = re.compile(_translate_pattern(pat))
|
||||||
|
match = _pat_cache[pat].match
|
||||||
|
return filter(match, names)
|
||||||
|
Loading…
Reference in New Issue
Block a user