diff --git a/doc/ext/bro.py b/doc/ext/bro.py index 5818038a4c..a4f0142ce3 100644 --- a/doc/ext/bro.py +++ b/doc/ext/bro.py @@ -4,6 +4,9 @@ def setup(Sphinx): Sphinx.add_domain(BroDomain) + Sphinx.add_node(see) + Sphinx.add_directive_to_domain('bro', 'see', SeeDirective) + Sphinx.connect('doctree-resolved', process_see_nodes) from sphinx import addnodes from sphinx.domains import Domain, ObjType, Index @@ -18,6 +21,51 @@ from docutils.parsers.rst import Directive from docutils.parsers.rst import directives from docutils.parsers.rst.roles import set_classes +class see(nodes.General, nodes.Element): + refs = [] + +class SeeDirective(Directive): + has_content = True + + def run(self): + n = see('') + n.refs = string.split(string.join(self.content)) + return [n] + +def process_see_nodes(app, doctree, fromdocname): + for node in doctree.traverse(see): + content = [] + para = nodes.paragraph() + para += nodes.Text("See also:", "See also:") + for name in node.refs: + join_str = " " + if name != node.refs[0]: + join_str = ", " + link_txt = join_str + name; + + if name not in app.env.domaindata['bro']['idtypes']: + # Just create the text and issue warning + app.env.warn(fromdocname, + 'unknown target for ".. bro:see:: %s"' % (name)) + para += nodes.Text(link_txt, link_txt) + else: + # Create a reference + typ = app.env.domaindata['bro']['idtypes'][name] + todocname = app.env.domaindata['bro']['objects'][(typ, name)] + + newnode = nodes.reference('', '') + innernode = nodes.literal(_(name), _(name)) + newnode['refdocname'] = todocname + newnode['refuri'] = app.builder.get_relative_uri( + fromdocname, todocname) + newnode['refuri'] += '#' + typ + '-' + name + newnode.append(innernode) + para += nodes.Text(join_str, join_str) + para += newnode + + content.append(para) + node.replace_self(content) + class BroGeneric(ObjectDescription): def update_type_map(self, idname): if 'idtypes' not in self.env.domaindata['bro']: @@ -194,7 +242,7 @@ class BroDomain(Domain): if typ == "see": if target not in self.data['idtypes']: self.env.warn(fromdocname, - 'unknown target for ":bro:see:`%s`' % (target)) + 'unknown target for ":bro:see:`%s`"' % (target)) return [] objtype = self.data['idtypes'][target] return make_refnode(builder, fromdocname, diff --git a/doc/scripts/example.bro b/doc/scripts/example.bro index f1b056c521..d2d0ec6879 100644 --- a/doc/scripts/example.bro +++ b/doc/scripts/example.bro @@ -8,8 +8,13 @@ ##! ##! There's also a custom role to reference any identifier node in ##! the Bro Sphinx domain that's good for "see alsos", e.g. -##! "see also :bro:see:`Example::a_var`, :bro:see:`Example::ONE`, and -##! :bro:see:`SSH::Info`" +##! +##! See also: :bro:see:`Example::a_var`, :bro:see:`Example::ONE`, +##! :bro:see:`SSH::Info` +##! +##! And a custom directive does the equivalent references: +##! +##! .. bro:see:: Example::a_var Example::ONE SSH::Info # Comments that use a single pound sign (#) are not significant to # a script's auto-generated documentation, but ones that use a diff --git a/testing/btest/Baseline/doc.autogen-reST-example/example.rst b/testing/btest/Baseline/doc.autogen-reST-example/example.rst index 5204c221c8..880fa0e171 100644 --- a/testing/btest/Baseline/doc.autogen-reST-example/example.rst +++ b/testing/btest/Baseline/doc.autogen-reST-example/example.rst @@ -17,8 +17,13 @@ these comments are transferred directly into the auto-generated There's also a custom role to reference any identifier node in the Bro Sphinx domain that's good for "see alsos", e.g. -"see also :bro:see:`Example::a_var`, :bro:see:`Example::ONE`, and -:bro:see:`SSH::Info`" + +See also: :bro:see:`Example::a_var`, :bro:see:`Example::ONE`, +:bro:see:`SSH::Info` + +And a custom directive does the equivalent references: + +.. bro:see:: Example::a_var Example::ONE SSH::Info :Imports: :doc:`policy/frameworks/software/vulnerable `