diff --git a/dargs/dargs.py b/dargs/dargs.py index 1dc73e0..84b97ac 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -506,7 +506,10 @@ def gen_doc_head(self, path: Optional[List[str]] = None, **kwargs) -> str: if self.alias: typesig += f", alias{'es' if len(self.alias) > 1 else ''}: " typesig += ', '.join(f"*{al}*" for al in self.alias) - head = f"{self.name}: \n{indent(typesig, INDENT)}" + head = f"{self.name}: " + if kwargs.get('use_sphinx_domain', False): + head = f".. dargs:argument:: {self.name}:\n :path: {'/'.join(path)}\n" + head += f"\n{indent(typesig, INDENT)}" if kwargs.get("make_anchor"): head = f"{make_rst_refid(path)}\n" + head return head @@ -711,6 +714,8 @@ def gen_doc_flag(self, path: Optional[List[str]] = None, **kwargs) -> str: if path is None: path = [] arg_path = [*path, self.flag_name] + if kwargs.get('use_sphinx_domain', False): + headdoc = f".. dargs:argument:: {self.flag_name}:\n :path: {'/'.join(arg_path)}\n" pathdoc = indent(f"| argument path: ``{'/'.join(arg_path)}`` ", INDENT) if kwargs.get("make_link"): if not kwargs.get("make_anchor"): diff --git a/dargs/sphinx.py b/dargs/sphinx.py index 1a4a42a..0b30ac5 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -23,6 +23,11 @@ from docutils.parsers.rst import Directive from docutils.parsers.rst.directives import unchanged +from sphinx import addnodes +from sphinx.directives import ObjectDescription +from sphinx.domains import Domain, ObjType +from sphinx.roles import XRefRole +from sphinx.util.nodes import make_refnode from .dargs import Argument, Variant @@ -59,14 +64,81 @@ def run(self): for argument in arguments: if not isinstance(argument, (Argument, Variant)): raise RuntimeError("The function doesn't return Argument") - rst = argument.gen_doc(make_anchor=True, make_link=True) + rst = argument.gen_doc(make_anchor=True, make_link=True, use_sphinx_domain=True) self.state_machine.insert_input(rst.split("\n"), "%s:%s" %(module_name, attr_name)) return [] +class DargsObject(ObjectDescription): + """dargs::argument directive. + + This directive creates a signature node for an argument. + """ + option_spec = dict( + path=unchanged, + ) + + def handle_signature(self, sig, signode): + signode += addnodes.desc_name(sig, sig) + return sig + + def add_target_and_index(self, name, sig, signode): + path = self.options['path'] + targetid = "%s:%s" % (self.objtype, path) + if targetid not in self.state.document.ids: + signode['names'].append(targetid) + signode['ids'].append(targetid) + signode['first'] = (not self.names) + self.state.document.note_explicit_target(signode) + # for cross-references + inv = self.env.domaindata['dargs']['arguments'] + if targetid in inv: + self.state.document.reporter.warning( + 'Duplicated argument "%s" described in "%s".' % + (targetid, self.env.doc2path(inv[targetid][0])), line=self.lineno) + inv[targetid] = (self.env.docname, self.objtype) + + self.indexnode['entries'].append(('pair', u'%s ; %s (%s) ' % (name, path, self.objtype.title()), targetid, 'main', None)) + + +class DargsDomain(Domain): + """Dargs domain. + + Includes: + - dargs::argument directive + - dargs::argument role + """ + name = 'dargs' + label = 'dargs' + object_types = { + 'argument': ObjType('argument', 'argument'), + } + directives = { + 'argument': DargsObject, + } + roles = { + 'argument': XRefRole(), + } + + initial_data = { + 'arguments': {}, # fullname -> docname, objtype + } + + def resolve_xref(self, env, fromdocname, builder, + typ, target, node, contnode): + """Resolve cross-references.""" + targetid = '%s:%s' % (typ, target) + obj = self.data['arguments'].get(targetid) + if obj is None: + return None + return make_refnode(builder, fromdocname, obj[0], targetid, + contnode, target) + + def setup(app): """Setup sphinx app.""" app.add_directive('dargs', DargsDirective) + app.add_domain(DargsDomain) return {'parallel_read_safe': True} diff --git a/docs/sphinx.rst b/docs/sphinx.rst index 75d2153..a8e1384 100644 --- a/docs/sphinx.rst +++ b/docs/sphinx.rst @@ -23,3 +23,23 @@ where `_test_argument` returns an :class:`Argument `. A :class:` .. dargs:: :module: dargs.sphinx :func: _test_argument + + +Cross-referencing Arguments +--------------------------- + +Both the following ways will create a cross-reference to the argument: + +.. code-block:: rst + + Both :dargs:argument:`this ` and :ref:`this ` will create a cross-reference to the argument! + +It will be rendered as: + + Both :dargs:argument:`this ` and :ref:`this ` will create a cross-reference to the argument! + + +Index page +---------- + +The arguments will be added into the :ref:`genindex` page. See :ref:`test_argument ` in the :ref:`genindex` page.