Use the QAPI object registry to generate a special index just for QAPI definitions. The index can show entries both by definition type and alphabetically.
The index can be linked from anywhere in the QEMU manual by using `qapi-index`. Signed-off-by: John Snow <js...@redhat.com> --- docs/qapi/index.rst | 6 +++- docs/sphinx/qapi-domain.py | 66 +++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst index 880fd17c709..051dc6b3a37 100644 --- a/docs/qapi/index.rst +++ b/docs/qapi/index.rst @@ -9,7 +9,8 @@ QAPI Domain Test doesn't create a cross-reference target and it isn't added to the index. - Check out the `genindex` for proof that foo-module is not present. + Check out the `genindex` or the `qapi-index` for proof that + foo-module is not present. .. qapi:module:: bar-module :no-typesetting: @@ -36,3 +37,6 @@ QAPI Domain Test The ``block-core`` module will have two entries in the `genindex`, under both "block-core" and "QAPI module". + + Modules will also be reported in the `qapi-index`, under the Modules + category and in the alphabetical categories that follow. diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py index ab80fd5f634..65409786119 100644 --- a/docs/sphinx/qapi-domain.py +++ b/docs/sphinx/qapi-domain.py @@ -12,6 +12,7 @@ Iterable, List, NamedTuple, + Optional, Tuple, cast, ) @@ -20,7 +21,12 @@ from docutils.parsers.rst import directives from sphinx import addnodes -from sphinx.domains import Domain, ObjType +from sphinx.domains import ( + Domain, + Index, + IndexEntry, + ObjType, +) from sphinx.locale import _, __ from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input @@ -74,9 +80,10 @@ class QAPIModule(SphinxDirective): a pass-through for the content body. Named section titles are allowed in the content body. - Use this directive to associate subsequent definitions with the - module they are defined in for purposes of search and QAPI index - organization. + Use this directive to create entries for the QAPI module in the + global index and the qapi index; as well as to associate subsequent + definitions with the module they are defined in for purposes of + search and QAPI index organization. :arg: The name of the module. :opt no-index: Don't add cross-reference targets or index entries. @@ -155,6 +162,52 @@ def run(self) -> List[Node]: return ret +class QAPIIndex(Index): + """ + Index subclass to provide the QAPI definition index. + """ + + name = "index" + localname = _("QAPI Index") + shortname = _("QAPI Index") + + def generate( + self, + docnames: Optional[Iterable[str]] = None, + ) -> Tuple[List[Tuple[str, List[IndexEntry]]], bool]: + assert isinstance(self.domain, QAPIDomain) + content: Dict[str, List[IndexEntry]] = {} + collapse = False + + # list of all object (name, ObjectEntry) pairs, sorted by name + objects = sorted(self.domain.objects.items(), key=lambda x: x[0].lower()) + + for objname, obj in objects: + if docnames and obj.docname not in docnames: + continue + + # Strip the module name out: + objname = objname.split(".")[-1] + + # Add an alphabetical entry: + entries = content.setdefault(objname[0].upper(), []) + entries.append( + IndexEntry(objname, 0, obj.docname, obj.node_id, obj.objtype, "", "") + ) + + # Add a categorical entry: + category = obj.objtype.title() + "s" + entries = content.setdefault(category, []) + entries.append(IndexEntry(objname, 0, obj.docname, obj.node_id, "", "", "")) + + # alphabetically sort categories; type names first, ABC entries last. + sorted_content = sorted( + content.items(), + key=lambda x: (len(x[0]) == 1, x[0]), + ) + return sorted_content, collapse + + class QAPIDomain(Domain): """QAPI language domain.""" @@ -182,7 +235,10 @@ class QAPIDomain(Domain): "objects": {}, # fullname -> ObjectEntry } - indices = [] + # Index pages to generate; each entry is an Index class. + indices = [ + QAPIIndex, + ] @property def objects(self) -> Dict[str, ObjectEntry]: -- 2.44.0