diff --git a/CHANGES b/CHANGES index 27a249822..a4f62a25a 100644 --- a/CHANGES +++ b/CHANGES @@ -11,11 +11,13 @@ Deprecated ---------- * The ``decode`` argument of ``sphinx.pycode.ModuleAnalyzer()`` +* ``sphinx.directives.other.Index`` * ``sphinx.environment.BuildEnvironment.indexentries`` * ``sphinx.environment.collectors.indexentries.IndexEntriesCollector`` * ``sphinx.io.FiletypeNotFoundError`` * ``sphinx.io.get_filetype()`` * ``sphinx.pycode.ModuleAnalyzer.encoding`` +* ``sphinx.roles.Index`` * ``sphinx.util.detect_encoding()`` * ``sphinx.util.get_module_source()`` diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 14a90548b..f1c03ec54 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -31,6 +31,11 @@ The following is a list of deprecated interfaces. - 4.0 - N/A + * - ``sphinx.directives.other.Index`` + - 2.4 + - 4.0 + - ``sphinx.domains.index.IndexDirective`` + * - ``sphinx.environment.BuildEnvironment.indexentries`` - 2.4 - 4.0 @@ -56,6 +61,11 @@ The following is a list of deprecated interfaces. - 4.0 - N/A + * - ``sphinx.roles.Index`` + - 2.4 + - 4.0 + - ``sphinx.domains.index.IndexRole`` + * - ``sphinx.util.detect_encoding()`` - 2.4 - 4.0 diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py index 393df0ca9..713e41ca8 100644 --- a/sphinx/directives/__init__.py +++ b/sphinx/directives/__init__.py @@ -253,12 +253,13 @@ from sphinx.directives.code import ( # noqa Highlight, CodeBlock, LiteralInclude ) from sphinx.directives.other import ( # noqa - TocTree, Author, Index, VersionChange, SeeAlso, + TocTree, Author, VersionChange, SeeAlso, TabularColumns, Centered, Acks, HList, Only, Include, Class ) from sphinx.directives.patches import ( # noqa Figure, Meta ) +from sphinx.domains.index import IndexDirective # noqa deprecated_alias('sphinx.directives', { @@ -267,7 +268,7 @@ deprecated_alias('sphinx.directives', 'LiteralInclude': LiteralInclude, 'TocTree': TocTree, 'Author': Author, - 'Index': Index, + 'Index': IndexDirective, 'VersionChange': VersionChange, 'SeeAlso': SeeAlso, 'TabularColumns': TabularColumns, diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index a5a2831d6..8a0c5051a 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -18,12 +18,13 @@ from docutils.parsers.rst.directives.misc import Class from docutils.parsers.rst.directives.misc import Include as BaseInclude from sphinx import addnodes +from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.domains.changeset import VersionChange # NOQA # for compatibility from sphinx.locale import _ from sphinx.util import url_re, docname_join from sphinx.util.docutils import SphinxDirective from sphinx.util.matching import Matcher, patfilter -from sphinx.util.nodes import explicit_title_re, process_index_entry +from sphinx.util.nodes import explicit_title_re if False: # For type annotation @@ -182,30 +183,6 @@ class Author(SphinxDirective): return ret -class Index(SphinxDirective): - """ - Directive to add entries to the index. - """ - has_content = False - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} # type: Dict - - def run(self) -> List[Node]: - arguments = self.arguments[0].split('\n') - targetid = 'index-%s' % self.env.new_serialno('index') - targetnode = nodes.target('', '', ids=[targetid]) - self.state.document.note_explicit_target(targetnode) - indexnode = addnodes.index() - indexnode['entries'] = [] - indexnode['inline'] = False - self.set_source_info(indexnode) - for entry in arguments: - indexnode['entries'].extend(process_index_entry(entry, targetid)) - return [indexnode, targetnode] - - class SeeAlso(BaseAdmonition): """ An admonition mentioning things to look at as reference. @@ -383,12 +360,21 @@ class Include(BaseInclude, SphinxDirective): return super().run() +# Import old modules here for compatibility +from sphinx.domains.index import IndexDirective # NOQA + +deprecated_alias('sphinx.directives.other', + { + 'Index': IndexDirective, + }, + RemovedInSphinx40Warning) + + def setup(app: "Sphinx") -> Dict[str, Any]: directives.register_directive('toctree', TocTree) directives.register_directive('sectionauthor', Author) directives.register_directive('moduleauthor', Author) directives.register_directive('codeauthor', Author) - directives.register_directive('index', Index) directives.register_directive('seealso', SeeAlso) directives.register_directive('tabularcolumns', TabularColumns) directives.register_directive('centered', Centered) diff --git a/sphinx/domains/index.py b/sphinx/domains/index.py index 4b1fd2bb6..046fbe158 100644 --- a/sphinx/domains/index.py +++ b/sphinx/domains/index.py @@ -10,14 +10,20 @@ from typing import Any, Dict, Iterable, List, Tuple -from docutils.nodes import Node +from docutils import nodes +from docutils.nodes import Node, system_message from sphinx import addnodes -from sphinx.application import Sphinx from sphinx.domains import Domain from sphinx.environment import BuildEnvironment from sphinx.util import logging from sphinx.util import split_index_msg +from sphinx.util.docutils import ReferenceRole, SphinxDirective +from sphinx.util.nodes import process_index_entry + +if False: + # For type annotation + from sphinx.application import Sphinx logger = logging.getLogger(__name__) @@ -54,8 +60,57 @@ class IndexDomain(Domain): entries.append(entry) -def setup(app: Sphinx) -> Dict[str, Any]: +class IndexDirective(SphinxDirective): + """ + Directive to add entries to the index. + """ + has_content = False + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = True + option_spec = {} # type: Dict + + def run(self) -> List[Node]: + arguments = self.arguments[0].split('\n') + targetid = 'index-%s' % self.env.new_serialno('index') + targetnode = nodes.target('', '', ids=[targetid]) + self.state.document.note_explicit_target(targetnode) + indexnode = addnodes.index() + indexnode['entries'] = [] + indexnode['inline'] = False + self.set_source_info(indexnode) + for entry in arguments: + indexnode['entries'].extend(process_index_entry(entry, targetid)) + return [indexnode, targetnode] + + +class IndexRole(ReferenceRole): + def run(self) -> Tuple[List[Node], List[system_message]]: + target_id = 'index-%s' % self.env.new_serialno('index') + if self.has_explicit_title: + # if an explicit target is given, process it as a full entry + title = self.title + entries = process_index_entry(self.target, target_id) + else: + # otherwise we just create a single entry + if self.target.startswith('!'): + title = self.title[1:] + entries = [('single', self.target[1:], target_id, 'main', None)] + else: + title = self.title + entries = [('single', self.target, target_id, '', None)] + + index = addnodes.index(entries=entries) + target = nodes.target('', '', ids=[target_id]) + text = nodes.Text(title, title) + self.set_source_info(index) + return [index, target, text], [] + + +def setup(app: "Sphinx") -> Dict[str, Any]: app.add_domain(IndexDomain) + app.add_directive('index', IndexDirective) + app.add_role('index', IndexRole()) return { 'version': 'builtin', diff --git a/sphinx/roles.py b/sphinx/roles.py index 5757183ce..477c90ae5 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -573,6 +573,7 @@ def index_role(typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner, class Index(ReferenceRole): def run(self) -> Tuple[List[Node], List[system_message]]: + warnings.warn('Index role is deprecated.', RemovedInSphinx40Warning) target_id = 'index-%s' % self.env.new_serialno('index') if self.has_explicit_title: # if an explicit target is given, process it as a full entry @@ -607,7 +608,6 @@ specific_docroles = { 'file': EmphasizedLiteral(), 'samp': EmphasizedLiteral(), 'abbr': Abbreviation(), - 'index': Index(), } # type: Dict[str, RoleFunction]