Implement semantic markup support for Ansible documentation in ansible-doc. (#80242)

pull/80278/head
Felix Fontein 2 years ago committed by GitHub
parent 4ca3a29cd2
commit a2dc5fcc7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
minor_changes:
- "ansible-doc - support semantic markup in text output (https://github.com/ansible/ansible/pull/80242)."

@ -362,12 +362,23 @@ class DocCLI(CLI, RoleMixin):
_ITALIC = re.compile(r"\bI\(([^)]+)\)") _ITALIC = re.compile(r"\bI\(([^)]+)\)")
_BOLD = re.compile(r"\bB\(([^)]+)\)") _BOLD = re.compile(r"\bB\(([^)]+)\)")
_MODULE = re.compile(r"\bM\(([^)]+)\)") _MODULE = re.compile(r"\bM\(([^)]+)\)")
_PLUGIN = re.compile(r"\bP\(([^#)]+)#([a-z]+)\)")
_LINK = re.compile(r"\bL\(([^)]+), *([^)]+)\)") _LINK = re.compile(r"\bL\(([^)]+), *([^)]+)\)")
_URL = re.compile(r"\bU\(([^)]+)\)") _URL = re.compile(r"\bU\(([^)]+)\)")
_REF = re.compile(r"\bR\(([^)]+), *([^)]+)\)") _REF = re.compile(r"\bR\(([^)]+), *([^)]+)\)")
_CONST = re.compile(r"\bC\(([^)]+)\)") _CONST = re.compile(r"\bC\(([^)]+)\)")
_SEM_PARAMETER_STRING = r"\(((?:[^\\)]+|\\.)+)\)"
_SEM_OPTION_NAME = re.compile(r"\bO" + _SEM_PARAMETER_STRING)
_SEM_OPTION_VALUE = re.compile(r"\bV" + _SEM_PARAMETER_STRING)
_SEM_ENV_VARIABLE = re.compile(r"\bE" + _SEM_PARAMETER_STRING)
_SEM_RET_VALUE = re.compile(r"\bRV" + _SEM_PARAMETER_STRING)
_RULER = re.compile(r"\bHORIZONTALLINE\b") _RULER = re.compile(r"\bHORIZONTALLINE\b")
# helper for unescaping
_UNESCAPE = re.compile(r"\\(.)")
_FQCN_TYPE_PREFIX_RE = re.compile(r'^([^.]+\.[^.]+\.[^#]+)#([a-z]+):(.*)$')
_IGNORE_MARKER = 'ignore:'
# rst specific # rst specific
_RST_NOTE = re.compile(r".. note::") _RST_NOTE = re.compile(r".. note::")
_RST_SEEALSO = re.compile(r".. seealso::") _RST_SEEALSO = re.compile(r".. seealso::")
@ -379,6 +390,33 @@ class DocCLI(CLI, RoleMixin):
super(DocCLI, self).__init__(args) super(DocCLI, self).__init__(args)
self.plugin_list = set() self.plugin_list = set()
@staticmethod
def _tty_ify_sem_simle(matcher):
text = DocCLI._UNESCAPE.sub(r'\1', matcher.group(1))
return f"`{text}'"
@staticmethod
def _tty_ify_sem_complex(matcher):
text = DocCLI._UNESCAPE.sub(r'\1', matcher.group(1))
value = None
if '=' in text:
text, value = text.split('=', 1)
m = DocCLI._FQCN_TYPE_PREFIX_RE.match(text)
if m:
plugin_fqcn = m.group(1)
plugin_type = m.group(2)
text = m.group(3)
elif text.startswith(DocCLI._IGNORE_MARKER):
text = text[len(DocCLI._IGNORE_MARKER):]
plugin_fqcn = plugin_type = ''
else:
plugin_fqcn = plugin_type = ''
if value is not None:
text = f"{text}={value}"
if plugin_fqcn and plugin_type:
return f"`{text}' (of {plugin_type} {plugin_fqcn})"
return f"`{text}'"
@classmethod @classmethod
def find_plugins(cls, path, internal, plugin_type, coll_filter=None): def find_plugins(cls, path, internal, plugin_type, coll_filter=None):
display.deprecated("find_plugins method as it is incomplete/incorrect. use ansible.plugins.list functions instead.", version='2.17') display.deprecated("find_plugins method as it is incomplete/incorrect. use ansible.plugins.list functions instead.", version='2.17')
@ -393,8 +431,13 @@ class DocCLI(CLI, RoleMixin):
t = cls._MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word] t = cls._MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word]
t = cls._URL.sub(r"\1", t) # U(word) => word t = cls._URL.sub(r"\1", t) # U(word) => word
t = cls._LINK.sub(r"\1 <\2>", t) # L(word, url) => word <url> t = cls._LINK.sub(r"\1 <\2>", t) # L(word, url) => word <url>
t = cls._PLUGIN.sub("[" + r"\1" + "]", t) # P(word#type) => [word]
t = cls._REF.sub(r"\1", t) # R(word, sphinx-ref) => word t = cls._REF.sub(r"\1", t) # R(word, sphinx-ref) => word
t = cls._CONST.sub(r"`\1'", t) # C(word) => `word' t = cls._CONST.sub(r"`\1'", t) # C(word) => `word'
t = cls._SEM_OPTION_NAME.sub(cls._tty_ify_sem_complex, t) # O(expr)
t = cls._SEM_OPTION_VALUE.sub(cls._tty_ify_sem_simle, t) # V(expr)
t = cls._SEM_ENV_VARIABLE.sub(cls._tty_ify_sem_simle, t) # E(expr)
t = cls._SEM_RET_VALUE.sub(cls._tty_ify_sem_complex, t) # RV(expr)
t = cls._RULER.sub("\n{0}\n".format("-" * 13), t) # HORIZONTALLINE => ------- t = cls._RULER.sub("\n{0}\n".format("-" * 13), t) # HORIZONTALLINE => -------
# remove rst # remove rst

@ -3,7 +3,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = r'''
--- ---
module: randommodule module: randommodule
short_description: A random module short_description: A random module
@ -18,22 +18,22 @@ deprecated:
removed_in: '3.0.0' removed_in: '3.0.0'
options: options:
test: test:
description: Some text. description: Some text. Consider not using O(ignore:foo=bar).
type: str type: str
version_added: 1.2.0 version_added: 1.2.0
sub: sub:
description: Suboptions. description: Suboptions. Contains O(sub.subtest), which can be set to V(123). You can use E(TEST_ENV) to set this.
type: dict type: dict
suboptions: suboptions:
subtest: subtest:
description: A suboption. description: A suboption. Not compatible to O(ansible.builtin.copy#module:path=c:\\foo\(1\).txt).
type: int type: int
version_added: 1.1.0 version_added: 1.1.0
# The following is the wrong syntax, and should not get processed # The following is the wrong syntax, and should not get processed
# by add_collection_to_versions_and_dates() # by add_collection_to_versions_and_dates()
options: options:
subtest2: subtest2:
description: Another suboption. description: Another suboption. Useful when P(ansible.builtin.shuffle#filter) is used with value V([a,b,\),d\\]).
type: float type: float
version_added: 1.1.0 version_added: 1.1.0
# The following is not supported in modules, and should not get processed # The following is not supported in modules, and should not get processed
@ -53,7 +53,7 @@ extends_documentation_fragment:
EXAMPLES = ''' EXAMPLES = '''
''' '''
RETURN = ''' RETURN = r'''
z_last: z_last:
description: A last result. description: A last result.
type: str type: str
@ -63,7 +63,8 @@ z_last:
m_middle: m_middle:
description: description:
- This should be in the middle. - This should be in the middle.
- Has some more data - Has some more data.
- Check out RV(m_middle.suboption) and compare it to RV(a_first=foo) and RV(community.general.foo#lookup:value).
type: dict type: dict
returned: success and 1st of month returned: success and 1st of month
contains: contains:
@ -74,7 +75,7 @@ m_middle:
version_added: 1.4.0 version_added: 1.4.0
a_first: a_first:
description: A first result. description: A first result. Use RV(a_first=foo\(bar\\baz\)bam).
type: str type: str
returned: success returned: success
''' '''

@ -14,7 +14,8 @@ DEPRECATED:
OPTIONS (= is mandatory): OPTIONS (= is mandatory):
- sub - sub
Suboptions. Suboptions. Contains `sub.subtest', which can be set to `123'.
You can use `TEST_ENV' to set this.
set_via: set_via:
env: env:
- deprecated: - deprecated:
@ -29,7 +30,8 @@ OPTIONS (= is mandatory):
OPTIONS: OPTIONS:
- subtest2 - subtest2
Another suboption. Another suboption. Useful when [ansible.builtin.shuffle]
is used with value `[a,b,),d\]'.
default: null default: null
type: float type: float
added in: version 1.1.0 added in: version 1.1.0
@ -39,14 +41,15 @@ OPTIONS (= is mandatory):
SUBOPTIONS: SUBOPTIONS:
- subtest - subtest
A suboption. A suboption. Not compatible to `path=c:\foo(1).txt' (of
module ansible.builtin.copy).
default: null default: null
type: int type: int
added in: version 1.1.0 of testns.testcol added in: version 1.1.0 of testns.testcol
- test - test
Some text. Some text. Consider not using `foo=bar'.
default: null default: null
type: str type: str
added in: version 1.2.0 of testns.testcol added in: version 1.2.0 of testns.testcol
@ -74,13 +77,15 @@ EXAMPLES:
RETURN VALUES: RETURN VALUES:
- a_first - a_first
A first result. A first result. Use `a_first=foo(bar\baz)bam'.
returned: success returned: success
type: str type: str
- m_middle - m_middle
This should be in the middle. This should be in the middle.
Has some more data Has some more data.
Check out `m_middle.suboption' and compare it to `a_first=foo'
and `value' (of lookup community.general.foo).
returned: success and 1st of month returned: success and 1st of month
type: dict type: dict

@ -19,7 +19,7 @@
"module": "randommodule", "module": "randommodule",
"options": { "options": {
"sub": { "sub": {
"description": "Suboptions.", "description": "Suboptions. Contains O(sub.subtest), which can be set to V(123). You can use E(TEST_ENV) to set this.",
"env": [ "env": [
{ {
"deprecated": { "deprecated": {
@ -34,14 +34,14 @@
], ],
"options": { "options": {
"subtest2": { "subtest2": {
"description": "Another suboption.", "description": "Another suboption. Useful when P(ansible.builtin.shuffle#filter) is used with value V([a,b,\\),d\\\\]).",
"type": "float", "type": "float",
"version_added": "1.1.0" "version_added": "1.1.0"
} }
}, },
"suboptions": { "suboptions": {
"subtest": { "subtest": {
"description": "A suboption.", "description": "A suboption. Not compatible to O(ansible.builtin.copy#module:path=c:\\\\foo\\(1\\).txt).",
"type": "int", "type": "int",
"version_added": "1.1.0", "version_added": "1.1.0",
"version_added_collection": "testns.testcol" "version_added_collection": "testns.testcol"
@ -50,7 +50,7 @@
"type": "dict" "type": "dict"
}, },
"test": { "test": {
"description": "Some text.", "description": "Some text. Consider not using O(ignore:foo=bar).",
"type": "str", "type": "str",
"version_added": "1.2.0", "version_added": "1.2.0",
"version_added_collection": "testns.testcol" "version_added_collection": "testns.testcol"
@ -78,7 +78,7 @@
"metadata": null, "metadata": null,
"return": { "return": {
"a_first": { "a_first": {
"description": "A first result.", "description": "A first result. Use RV(a_first=foo\\(bar\\\\baz\\)bam).",
"returned": "success", "returned": "success",
"type": "str" "type": "str"
}, },
@ -98,7 +98,8 @@
}, },
"description": [ "description": [
"This should be in the middle.", "This should be in the middle.",
"Has some more data" "Has some more data.",
"Check out RV(m_middle.suboption) and compare it to RV(a_first=foo) and RV(community.general.foo#lookup:value)."
], ],
"returned": "success and 1st of month", "returned": "success and 1st of month",
"type": "dict" "type": "dict"

Loading…
Cancel
Save