Add initial Python bindings documentation
[babeltrace.git] / doc / bindings / python / ext / bt2sphinxurl.py
diff --git a/doc/bindings/python/ext/bt2sphinxurl.py b/doc/bindings/python/ext/bt2sphinxurl.py
new file mode 100644 (file)
index 0000000..b3e2608
--- /dev/null
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: MIT
+#
+# Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com>
+#
+# This file is a Sphinx extension which adds the following roles:
+#
+# `bt2man`:
+#     A typical manual page reference, like `grep(1)`.
+#
+#     Example:
+#
+#         :bt2man:`grep(1)`
+#
+#     This role creates a simple inline literal node with the role's
+#     text if it's not a Babeltrace 2 manual page reference, or an
+#     external link to the corresponding online manual page (on
+#     `babeltrace.org`) with the appropriate project's version
+#     (`version` configuration entry) otherwise.
+#
+# `bt2link`:
+#     An external link with an URL in which a specific placeholder is
+#     replaced with the project's version.
+#
+#     The role's text follows the typical external link format, for
+#     example:
+#
+#         Link text <https://example.com/>
+#
+#     Any `@ver@` in the URL is replaced with the project's version
+#     (`version` configuration entry).
+#
+#     Example:
+#
+#         :bt2link:`libbabeltrace2 <https://babeltrace.org/docs/v@ver@/libbabeltrace2/>`
+
+import docutils
+import docutils.utils
+import docutils.nodes
+import re
+import functools
+
+
+def _bt2man_role(
+    bt2_version, name, rawtext, text, lineno, inliner, options=None, content=None
+):
+    # match a manual page reference
+    m = re.match(r'^([a-zA-Z0-9_.:-]+)\(([a-zA-Z0-9]+)\)$', text)
+
+    if not m:
+        msg = 'Cannot parse manual page reference `{}`'.format(text)
+        inliner.reporter.severe(msg, line=lineno)
+        return [inliner.problematic(rawtext, rawtext, msg)], [msg]
+
+    # matched manual page and volume
+    page = m.group(1)
+    vol = m.group(2)
+
+    # create nodes: `ret_node` is the node to return
+    page_node = docutils.nodes.strong(rawtext, page)
+    vol_node = docutils.nodes.inline(rawtext, '({})'.format(vol))
+    man_node = docutils.nodes.inline(rawtext, '', page_node, vol_node)
+    ret_node = docutils.nodes.literal(rawtext, '', man_node)
+
+    if page.startswith('babeltrace2'):
+        # Babeltrace 2 manual page: wrap `ret_node` with an external
+        # link node
+        url_tmpl = 'https://babeltrace.org/docs/v{ver}/man{vol}/{page}.{vol}/'
+        url = url_tmpl.format(ver=bt2_version, vol=vol, page=page)
+        ret_node = docutils.nodes.reference(
+            rawtext, '', ret_node, internal=False, refuri=url
+        )
+
+    return [ret_node], []
+
+
+def _bt2link_role(
+    bt2_version, name, rawtext, text, lineno, inliner, options=None, content=None
+):
+    # match link text and URL
+    m = re.match(r'^([^<]+) <([^>]+)>$', text)
+
+    if not m:
+        msg = 'Cannot parse link template `{}`'.format(text)
+        inliner.reporter.severe(msg, line=lineno)
+        return [inliner.problematic(rawtext, rawtext, msg)], [msg]
+
+    link_text = m.group(1)
+
+    # replace `@ver@` with the project's version
+    url = m.group(2).replace('@ver@', bt2_version)
+
+    # create and return an external link node
+    node = docutils.nodes.reference(rawtext, link_text, internal=False, refuri=url)
+    return [node], []
+
+
+def _add_roles(app):
+    # add the extension's roles; the role functions above expect the
+    # project's version as their first parameter
+    app.add_role('bt2man', functools.partial(_bt2man_role, app.config.version))
+    app.add_role('bt2link', functools.partial(_bt2link_role, app.config.version))
+
+
+def setup(app):
+    app.connect('builder-inited', _add_roles)
+    return {
+        'version': app.config.version,
+        'parallel_read_safe': True,
+    }
This page took 0.023744 seconds and 4 git commands to generate.