Skip to content

Commit

Permalink
doc: add ability to disambiguate clicmds
Browse files Browse the repository at this point in the history
Multiple daemons have the same CLI commands defined, but the current
directive used to document CLI commands only takes the command
definition string. Since CLI command objects can be cross-referenced
using the :clicmd: directive, and are placed in the index, each object
needs to be unique.

To accomplish this, add a custom directive. This directive extends the
directive class used by sphinx's add_object_type to add a :daemon:
option. By specifying this option where needed, the object name becomes
"(<daemon>) <definition>", disambiguating it.

Signed-off-by: Quentin Young <[email protected]>
  • Loading branch information
qlyoung committed Jun 26, 2024
1 parent aeeceef commit 31a66e1
Showing 1 changed file with 44 additions and 4 deletions.
48 changes: 44 additions & 4 deletions doc/user/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import pygments
import sphinx
from sphinx.highlighting import lexers
from sphinx.domains.std import GenericObject
from docutils.parsers.rst import directives

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
Expand Down Expand Up @@ -372,11 +374,49 @@ def vparse(s):
return a[:3]


# custom extensions here
class ClicmdDirective(GenericObject):
"""
Directive for documenting CLI commands.
The xref string, if no option is provided, will be the verbatim command
string. If the :daemon: option is provided, then it's
"(<daemon>) <command string>)".
Options:
:daemon: - specify the daemon this command belongs to. Useful for
disambiguating multiple definitions of the same command.
"""

has_content = True
required_arguments = 1
optional_arguments = 0
option_spec = {
**GenericObject.option_spec,
"daemon": directives.unchanged,
}

def handle_signature(self, sig, signode):
name = super().handle_signature(sig, signode)
daemon = self.options["daemon"] if "daemon" in self.options else ""
prefix = f"({daemon}) " if daemon else ""
return prefix + name

def run(self):
daemon = self.options["daemon"] if "daemon" in self.options else ""
if daemon:
self.indextemplate = f"pair: ({daemon}) %s; configuration command"
else:
self.indextemplate = f"pair: %s; configuration command"

nodes = super().run()

return nodes


def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
# node later on
app.add_object_type("clicmd", "clicmd", indextemplate="pair: %s; configuration command")
app.add_object_type("clicmd", "clicmd", objname="CLI command")
# Override the directive that was just created for us
app.add_directive_to_domain("std", "clicmd", ClicmdDirective, override=True)

# I dont care how stupid this is
if "add_js_file" in dir(app):
Expand Down

0 comments on commit 31a66e1

Please sign in to comment.