From dc00f2dc1d4d3f6435c31bf8d4777ff78b851d12 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Thu, 28 Sep 2023 20:11:31 -0400 Subject: [PATCH 1/2] doc: add ability to disambiguate clicmds 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 "() ", disambiguating it. Signed-off-by: Quentin Young --- doc/user/conf.py | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/doc/user/conf.py b/doc/user/conf.py index 629a972726..a36d4406f3 100644 --- a/doc/user/conf.py +++ b/doc/user/conf.py @@ -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 @@ -373,13 +375,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 + "() )". + + 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): From ffbad581fc2f3b6e75b59b0e91393dfe0039d861 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 26 Jun 2024 18:17:07 -0400 Subject: [PATCH 2/2] doc: do not use custom directive on old sphinx Not supported. Signed-off-by: Quentin Young --- doc/user/conf.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/user/conf.py b/doc/user/conf.py index a36d4406f3..395875520d 100644 --- a/doc/user/conf.py +++ b/doc/user/conf.py @@ -415,9 +415,14 @@ def run(self): def setup(app): - 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) + if int(sphinx.__version__.split(".")[0]) >= 2: + app.add_object_type("clicmd", "clicmd", objname="CLI command") + app.add_directive_to_domain("std", "clicmd", ClicmdDirective, override=True) + else: + app.add_object_type( + "clicmd", "clicmd", indextemplate="pair: %s; configuration command" + ) # I dont care how stupid this is if "add_js_file" in dir(app):