Commit | Line | Data |
---|---|---|
ba64dfcc SM |
1 | # SPDX-License-Identifier: MIT |
2 | # | |
3 | # Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com> | |
4 | # | |
5 | # This file is a Sphinx extension which adds the following roles: | |
6 | # | |
7 | # `bt2man`: | |
8 | # A typical manual page reference, like `grep(1)`. | |
9 | # | |
10 | # Example: | |
11 | # | |
12 | # :bt2man:`grep(1)` | |
13 | # | |
14 | # This role creates a simple inline literal node with the role's | |
15 | # text if it's not a Babeltrace 2 manual page reference, or an | |
16 | # external link to the corresponding online manual page (on | |
17 | # `babeltrace.org`) with the appropriate project's version | |
18 | # (`version` configuration entry) otherwise. | |
19 | # | |
20 | # `bt2link`: | |
21 | # An external link with an URL in which a specific placeholder is | |
22 | # replaced with the project's version. | |
23 | # | |
24 | # The role's text follows the typical external link format, for | |
25 | # example: | |
26 | # | |
27 | # Link text <https://example.com/> | |
28 | # | |
29 | # Any `@ver@` in the URL is replaced with the project's version | |
30 | # (`version` configuration entry). | |
31 | # | |
32 | # Example: | |
33 | # | |
34 | # :bt2link:`libbabeltrace2 <https://babeltrace.org/docs/v@ver@/libbabeltrace2/>` | |
35 | ||
ba64dfcc SM |
36 | import re |
37 | import functools | |
38 | ||
5995b304 SM |
39 | import docutils |
40 | import docutils.nodes | |
41 | import docutils.utils | |
42 | ||
ba64dfcc SM |
43 | |
44 | def _bt2man_role( | |
45 | bt2_version, name, rawtext, text, lineno, inliner, options=None, content=None | |
46 | ): | |
47 | # match a manual page reference | |
f5567ea8 | 48 | m = re.match(r"^([a-zA-Z0-9_.:-]+)\(([a-zA-Z0-9]+)\)$", text) |
ba64dfcc SM |
49 | |
50 | if not m: | |
f5567ea8 | 51 | msg = "Cannot parse manual page reference `{}`".format(text) |
ba64dfcc SM |
52 | inliner.reporter.severe(msg, line=lineno) |
53 | return [inliner.problematic(rawtext, rawtext, msg)], [msg] | |
54 | ||
55 | # matched manual page and volume | |
56 | page = m.group(1) | |
57 | vol = m.group(2) | |
58 | ||
59 | # create nodes: `ret_node` is the node to return | |
60 | page_node = docutils.nodes.strong(rawtext, page) | |
f5567ea8 FD |
61 | vol_node = docutils.nodes.inline(rawtext, "({})".format(vol)) |
62 | man_node = docutils.nodes.inline(rawtext, "", page_node, vol_node) | |
63 | ret_node = docutils.nodes.literal(rawtext, "", man_node) | |
ba64dfcc | 64 | |
f5567ea8 | 65 | if page.startswith("babeltrace2"): |
ba64dfcc SM |
66 | # Babeltrace 2 manual page: wrap `ret_node` with an external |
67 | # link node | |
f5567ea8 | 68 | url_tmpl = "https://babeltrace.org/docs/v{ver}/man{vol}/{page}.{vol}/" |
ba64dfcc SM |
69 | url = url_tmpl.format(ver=bt2_version, vol=vol, page=page) |
70 | ret_node = docutils.nodes.reference( | |
f5567ea8 | 71 | rawtext, "", ret_node, internal=False, refuri=url |
ba64dfcc SM |
72 | ) |
73 | ||
74 | return [ret_node], [] | |
75 | ||
76 | ||
77 | def _bt2link_role( | |
78 | bt2_version, name, rawtext, text, lineno, inliner, options=None, content=None | |
79 | ): | |
80 | # match link text and URL | |
f5567ea8 | 81 | m = re.match(r"^([^<]+) <([^>]+)>$", text) |
ba64dfcc SM |
82 | |
83 | if not m: | |
f5567ea8 | 84 | msg = "Cannot parse link template `{}`".format(text) |
ba64dfcc SM |
85 | inliner.reporter.severe(msg, line=lineno) |
86 | return [inliner.problematic(rawtext, rawtext, msg)], [msg] | |
87 | ||
88 | link_text = m.group(1) | |
89 | ||
90 | # replace `@ver@` with the project's version | |
f5567ea8 | 91 | url = m.group(2).replace("@ver@", bt2_version) |
ba64dfcc SM |
92 | |
93 | # create and return an external link node | |
94 | node = docutils.nodes.reference(rawtext, link_text, internal=False, refuri=url) | |
95 | return [node], [] | |
96 | ||
97 | ||
98 | def _add_roles(app): | |
99 | # add the extension's roles; the role functions above expect the | |
100 | # project's version as their first parameter | |
f5567ea8 FD |
101 | app.add_role("bt2man", functools.partial(_bt2man_role, app.config.version)) |
102 | app.add_role("bt2link", functools.partial(_bt2link_role, app.config.version)) | |
ba64dfcc SM |
103 | |
104 | ||
105 | def setup(app): | |
f5567ea8 | 106 | app.connect("builder-inited", _add_roles) |
ba64dfcc | 107 | return { |
f5567ea8 FD |
108 | "version": app.config.version, |
109 | "parallel_read_safe": True, | |
ba64dfcc | 110 | } |