From 7ca9a459eb51ab110680d8221ddefeb0ffc6e95f Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 Nov 2014 17:19:26 -0500 Subject: Utilities/Sphinx: Add index entries for cross-references Add a document transform to insert index and target nodes just before any CMake domain cross-reference node. This will make references to CMake domain objects appear in the index. Also add a comment explaining why it cannot be done in a result_nodes method of the CMakeXRefRole. --- Utilities/Sphinx/cmake.py | 48 ++++++++++++++++++++++++++++++++-- Utilities/Sphinx/create_identifiers.py | 2 +- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 2629bb3..ec39596 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -130,8 +130,8 @@ class _cmake_index_entry: def __init__(self, desc): self.desc = desc - def __call__(self, title, targetid): - return ('pair', u'%s ; %s' % (self.desc, title), targetid, 'main') + def __call__(self, title, targetid, main = 'main'): + return ('pair', u'%s ; %s' % (self.desc, title), targetid, main) _cmake_index_objs = { 'command': _cmake_index_entry('command'), @@ -257,6 +257,49 @@ class CMakeXRefRole(XRefRole): break return XRefRole.__call__(self, typ, rawtext, text, *args, **keys) + # We cannot insert index nodes using the result_nodes method + # because CMakeXRefRole is processed before substitution_reference + # nodes are evaluated so target nodes (with 'ids' fields) would be + # duplicated in each evaluted substitution replacement. The + # docutils substitution transform does not allow this. Instead we + # use our own CMakeXRefTransform below to add index entries after + # substitutions are completed. + # + # def result_nodes(self, document, env, node, is_ref): + # pass + +class CMakeXRefTransform(Transform): + + # Run this transform early since we insert nodes we want + # treated as if they were written in the documents, but + # after the sphinx (210) and docutils (220) substitutions. + default_priority = 221 + + def apply(self): + env = self.document.settings.env + + # Find CMake cross-reference nodes and add index and target + # nodes for them. + for ref in self.document.traverse(addnodes.pending_xref): + if not ref['refdomain'] == 'cmake': + continue + + objtype = ref['reftype'] + make_index_entry = _cmake_index_objs.get(objtype) + if not make_index_entry: + continue + + objname = ref['reftarget'] + targetnum = env.new_serialno('index-%s:%s' % (objtype, objname)) + + targetid = 'index-%s-%s:%s' % (targetnum, objtype, objname) + targetnode = nodes.target('', '', ids=[targetid]) + self.document.note_explicit_target(targetnode) + + indexnode = addnodes.index() + indexnode['entries'] = [make_index_entry(objname, targetid, '')] + ref.replace_self([indexnode, targetnode, ref]) + class CMakeDomain(Domain): """CMake domain.""" name = 'cmake' @@ -336,4 +379,5 @@ class CMakeDomain(Domain): def setup(app): app.add_directive('cmake-module', CMakeModule) app.add_transform(CMakeTransform) + app.add_transform(CMakeXRefTransform) app.add_domain(CMakeDomain) diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py index 7715e53..3fe3fcb 100755 --- a/Utilities/Sphinx/create_identifiers.py +++ b/Utilities/Sphinx/create_identifiers.py @@ -34,7 +34,7 @@ for line in lines: for domain_object_string, domain_object_type in mapping: if "