mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 10:50:16 -06:00
Utilities/Sphinx: Add a directive to document command signatures
Add a `signature` directive to offer a CMake version of Sphinx's `function` directive, similar to that found in other domains (py, cpp, etc.). Like others, this takes one or more signatures as arguments and creates dt/dd nodes from the signatures and the directive contents.
This commit is contained in:
@@ -241,6 +241,69 @@ Document a "genex" object:
|
||||
|
||||
The directive requires a single argument, the generator expression name.
|
||||
|
||||
``signature`` directive
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Document `CMake Command Signatures <Style: CMake Command Signatures_>`_
|
||||
within a ``Help/command/<command-name>.rst`` document.
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. signature:: <command-name>(<signature>)
|
||||
|
||||
This indented block documents one or more signatures of a CMake command.
|
||||
|
||||
The ``signature`` directive requires one argument, the signature summary:
|
||||
|
||||
* One or more signatures must immediately follow the ``::``.
|
||||
The first signature may optionally be placed on the same line.
|
||||
A blank line following the ``signature`` directive will result in a
|
||||
documentation generation error: ``1 argument(s) required, 0 supplied``.
|
||||
|
||||
* Signatures may be split across multiple lines, but the final ``)`` of each
|
||||
signature must be the last character on its line.
|
||||
|
||||
* Blank lines between signatures are not allowed. (Content after a blank line
|
||||
is treated as part of the description.)
|
||||
|
||||
* Whitespace in signatures is not preserved. To document a complex signature,
|
||||
abbreviate it in the ``signature`` directive argument and specify the full
|
||||
signature in a ``code-block`` in the description.
|
||||
|
||||
The ``signature`` directive generates a document-local hyperlink target
|
||||
for each signature:
|
||||
|
||||
* Default target names are automatically extracted from leading "keyword"
|
||||
arguments in the signatures, where a keyword is any sequence of
|
||||
non-space starting with a letter. For example, the signature
|
||||
``string(REGEX REPLACE <match-regex> ...)`` generates the target
|
||||
``REGEX REPLACE``, similar to ``.. _`REGEX REPLACE`:``.
|
||||
|
||||
* Custom target names may be specified using a ``:target:`` option.
|
||||
For example:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. signature::
|
||||
cmake_path(GET <path-var> ROOT_NAME <out-var>)
|
||||
cmake_path(GET <path-var> ROOT_PATH <out-var>)
|
||||
:target:
|
||||
GET ROOT_NAME
|
||||
GET ROOT_PATH
|
||||
|
||||
Provide a custom target name for each signature, one per line.
|
||||
The first target may optionally be placed on the same line as ``:target:``.
|
||||
|
||||
* If a target name is already in use earlier in the document, no hyperlink
|
||||
target will be generated.
|
||||
|
||||
* The targets may be referenced from within the same document using
|
||||
```REF`_`` or ```TEXT <REF_>`_`` syntax. Like reStructuredText section
|
||||
headers, the targets do not work with Sphinx ``:ref:`` syntax.
|
||||
|
||||
The directive treats its content as the documentation of the signature(s).
|
||||
Indent the signature documentation accordingly.
|
||||
|
||||
``variable`` directive
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -374,11 +437,11 @@ paragraph.
|
||||
Style: CMake Command Signatures
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Command signatures should be marked up as plain literal blocks, not as
|
||||
cmake ``code-blocks``.
|
||||
|
||||
Signatures are separated from preceding content by a section header.
|
||||
That is, use:
|
||||
A ``Help/command/<command-name>.rst`` document defines one ``command``
|
||||
object in the `CMake Domain`_, but some commands have multiple signatures.
|
||||
Use the CMake Domain's `signature directive`_ to document each signature.
|
||||
Separate signatures from preceding content by a section header.
|
||||
For example:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
@@ -387,17 +450,23 @@ That is, use:
|
||||
Normal Libraries
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
.. signature::
|
||||
add_library(<lib> ...)
|
||||
|
||||
This signature is used for ...
|
||||
This signature is used for ...
|
||||
|
||||
Signatures of commands should wrap optional parts with square brackets,
|
||||
and should mark list of optional arguments with an ellipsis (``...``).
|
||||
Elements of the signature which are specified by the user should be
|
||||
specified with angle brackets, and may be referred to in prose using
|
||||
``inline-literal`` syntax.
|
||||
Use the following conventions in command signature documentation:
|
||||
|
||||
* Use an angle-bracket ``<placeholder>`` for arguments to be specified
|
||||
by the caller. Refer to them in prose using
|
||||
`inline literal <Style: Inline Literals_>`_ syntax.
|
||||
|
||||
* Wrap optional parts with square brackets.
|
||||
|
||||
* Mark repeatable parts with a trailing ellipsis (``...``).
|
||||
|
||||
The ``signature`` directive may be used multiple times for different
|
||||
signatures of the same command.
|
||||
|
||||
Style: Boolean Constants
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -20,7 +20,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
|
||||
: OS(os)
|
||||
, DocRoot(std::move(docroot))
|
||||
, CMakeDirective("^.. (cmake:)?("
|
||||
"command|envvar|genex|variable"
|
||||
"command|envvar|genex|signature|variable"
|
||||
")::[ \t]+([^ \t\n]+)$")
|
||||
, CMakeModuleDirective("^.. cmake-module::[ \t]+([^ \t\n]+)$")
|
||||
, ParsedLiteralDirective("^.. parsed-literal::[ \t]*(.*)$")
|
||||
|
||||
@@ -70,6 +70,14 @@ Bracket Comment Content
|
||||
|
||||
Generator expression $<OTHER_GENEX> description.
|
||||
|
||||
.. cmake:signature:: some_command(SOME_SIGNATURE)
|
||||
|
||||
Command some_command SOME_SIGNATURE description.
|
||||
|
||||
.. signature:: other_command(OTHER_SIGNATURE)
|
||||
|
||||
Command other_command OTHER_SIGNATURE description.
|
||||
|
||||
.. cmake:variable:: some_var
|
||||
|
||||
Variable some_var description.
|
||||
|
||||
@@ -73,6 +73,14 @@ Inline literal ``__`` followed by inline link `Link Text <InternalDest_>`_.
|
||||
|
||||
Generator expression $<OTHER_GENEX> description.
|
||||
|
||||
.. cmake:signature:: some_command(SOME_SIGNATURE)
|
||||
|
||||
Command some_command SOME_SIGNATURE description.
|
||||
|
||||
.. signature:: other_command(OTHER_SIGNATURE)
|
||||
|
||||
Command other_command OTHER_SIGNATURE description.
|
||||
|
||||
.. cmake:variable:: some_var
|
||||
|
||||
Variable some_var description.
|
||||
|
||||
@@ -16,6 +16,9 @@ from pygments.lexers import CMakeLexer
|
||||
from pygments.token import Name, Operator, Punctuation, String, Text, Comment, Generic, Whitespace, Number
|
||||
from pygments.lexer import bygroups
|
||||
|
||||
# RE to split multiple command signatures
|
||||
sig_end_re = re.compile(r'(?<=[)])\n')
|
||||
|
||||
# Notes on regular expressions below:
|
||||
# - [\.\+-] are needed for string constants like gtk+-2.0
|
||||
# - Unix paths are recognized by '/'; support for Windows paths may be added if needed
|
||||
@@ -57,14 +60,16 @@ CMakeLexer.tokens["root"] = [
|
||||
# (r'[^<>\])\}\|$"# \t\n]+', Name.Exception), # fallback, for debugging only
|
||||
]
|
||||
|
||||
from docutils.utils.code_analyzer import Lexer, LexerError
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
from docutils.transforms import Transform
|
||||
from docutils import io, nodes
|
||||
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.directives import ObjectDescription, nl_escape_re
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.util.nodes import make_refnode
|
||||
from sphinx.util import ws_re
|
||||
from sphinx import addnodes
|
||||
|
||||
sphinx_before_1_4 = False
|
||||
@@ -286,9 +291,9 @@ class CMakeObject(ObjectDescription):
|
||||
|
||||
def add_target_and_index(self, name, sig, signode):
|
||||
if self.objtype == 'command':
|
||||
targetname = name.lower()
|
||||
targetname = name.lower()
|
||||
else:
|
||||
targetname = name
|
||||
targetname = name
|
||||
targetid = '%s:%s' % (self.objtype, targetname)
|
||||
if targetid not in self.state.document.ids:
|
||||
signode['names'].append(targetid)
|
||||
@@ -302,6 +307,79 @@ class CMakeObject(ObjectDescription):
|
||||
if make_index_entry:
|
||||
self.indexnode['entries'].append(make_index_entry(name, targetid))
|
||||
|
||||
class CMakeSignatureObject(CMakeObject):
|
||||
object_type = 'signature'
|
||||
|
||||
option_spec = {
|
||||
'target': directives.unchanged,
|
||||
}
|
||||
|
||||
def get_signatures(self):
|
||||
content = nl_escape_re.sub('', self.arguments[0])
|
||||
lines = sig_end_re.split(content)
|
||||
return [ws_re.sub(' ', line.strip()) for line in lines]
|
||||
|
||||
def handle_signature(self, sig, signode):
|
||||
language = 'cmake'
|
||||
classes = ['code', 'cmake', 'highlight']
|
||||
|
||||
node = addnodes.desc_name(sig, '', classes=classes)
|
||||
|
||||
try:
|
||||
tokens = Lexer(sig, language, 'short')
|
||||
except LexerError as error:
|
||||
if self.state.document.settings.report_level > 2:
|
||||
# Silently insert without syntax highlighting.
|
||||
tokens = Lexer(sig, language, 'none')
|
||||
else:
|
||||
raise self.warning(error)
|
||||
|
||||
for classes, value in tokens:
|
||||
if classes:
|
||||
node += nodes.inline(value, value, classes=classes)
|
||||
else:
|
||||
node += nodes.Text(value)
|
||||
|
||||
signode.clear()
|
||||
signode += node
|
||||
|
||||
return sig
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.targetnames = {}
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def add_target_and_index(self, name, sig, signode):
|
||||
if name in self.targetnames:
|
||||
targetname = self.targetnames[name].lower()
|
||||
else:
|
||||
def extract_keywords(params):
|
||||
for p in params:
|
||||
if p[0].isalpha():
|
||||
yield p
|
||||
else:
|
||||
return
|
||||
|
||||
keywords = extract_keywords(name.split('(')[1].split())
|
||||
targetname = ' '.join(keywords).lower()
|
||||
targetid = nodes.make_id(targetname)
|
||||
|
||||
if targetid not in self.state.document.ids:
|
||||
signode['names'].append(targetname)
|
||||
signode['ids'].append(targetid)
|
||||
signode['first'] = (not self.names)
|
||||
self.state.document.note_explicit_target(signode)
|
||||
|
||||
def run(self):
|
||||
targets = self.options.get('target')
|
||||
if targets is not None:
|
||||
signatures = self.get_signatures()
|
||||
targets = [t.strip() for t in targets.split('\n')]
|
||||
for signature, target in zip(signatures, targets):
|
||||
self.targetnames[signature] = target
|
||||
|
||||
return super().run()
|
||||
|
||||
class CMakeXRefRole(XRefRole):
|
||||
|
||||
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
|
||||
@@ -411,6 +489,7 @@ class CMakeDomain(Domain):
|
||||
'command': CMakeObject,
|
||||
'envvar': CMakeObject,
|
||||
'genex': CMakeObject,
|
||||
'signature': CMakeSignatureObject,
|
||||
'variable': CMakeObject,
|
||||
# Other `object_types` cannot be created except by the `CMakeTransform`
|
||||
}
|
||||
|
||||
@@ -17,6 +17,29 @@ div.sphinxsidebarwrapper {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
|
||||
/* Apply <pre> style (from classic.css) to signature directive argument. */
|
||||
.signature .sig {
|
||||
padding: 5px;
|
||||
background-color: #eeeeee;
|
||||
color: #333333;
|
||||
line-height: 120%;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* Add additional styling to signature directive argument. */
|
||||
.signature .sig {
|
||||
margin-bottom: 5px;
|
||||
padding-left: calc(5px + 3em);
|
||||
text-indent: -3em;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.signature .sig .code.sig-name {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Remove unwanted margin in case list item contains a div-wrapping
|
||||
directive like `.. versionadded` or `.. deprecated`. */
|
||||
dd > :first-child > p {
|
||||
|
||||
Reference in New Issue
Block a user