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 | ||
36 | import docutils | |
37 | import docutils.utils | |
38 | import docutils.nodes | |
39 | import re | |
40 | import functools | |
41 | ||
42 | ||
43 | def _bt2man_role( | |
44 | bt2_version, name, rawtext, text, lineno, inliner, options=None, content=None | |
45 | ): | |
46 | # match a manual page reference | |
47 | m = re.match(r'^([a-zA-Z0-9_.:-]+)\(([a-zA-Z0-9]+)\)$', text) | |
48 | ||
49 | if not m: | |
50 | msg = 'Cannot parse manual page reference `{}`'.format(text) | |
51 | inliner.reporter.severe(msg, line=lineno) | |
52 | return [inliner.problematic(rawtext, rawtext, msg)], [msg] | |
53 | ||
54 | # matched manual page and volume | |
55 | page = m.group(1) | |
56 | vol = m.group(2) | |
57 | ||
58 | # create nodes: `ret_node` is the node to return | |
59 | page_node = docutils.nodes.strong(rawtext, page) | |
60 | vol_node = docutils.nodes.inline(rawtext, '({})'.format(vol)) | |
61 | man_node = docutils.nodes.inline(rawtext, '', page_node, vol_node) | |
62 | ret_node = docutils.nodes.literal(rawtext, '', man_node) | |
63 | ||
64 | if page.startswith('babeltrace2'): | |
65 | # Babeltrace 2 manual page: wrap `ret_node` with an external | |
66 | # link node | |
67 | url_tmpl = 'https://babeltrace.org/docs/v{ver}/man{vol}/{page}.{vol}/' | |
68 | url = url_tmpl.format(ver=bt2_version, vol=vol, page=page) | |
69 | ret_node = docutils.nodes.reference( | |
70 | rawtext, '', ret_node, internal=False, refuri=url | |
71 | ) | |
72 | ||
73 | return [ret_node], [] | |
74 | ||
75 | ||
76 | def _bt2link_role( | |
77 | bt2_version, name, rawtext, text, lineno, inliner, options=None, content=None | |
78 | ): | |
79 | # match link text and URL | |
80 | m = re.match(r'^([^<]+) <([^>]+)>$', text) | |
81 | ||
82 | if not m: | |
83 | msg = 'Cannot parse link template `{}`'.format(text) | |
84 | inliner.reporter.severe(msg, line=lineno) | |
85 | return [inliner.problematic(rawtext, rawtext, msg)], [msg] | |
86 | ||
87 | link_text = m.group(1) | |
88 | ||
89 | # replace `@ver@` with the project's version | |
90 | url = m.group(2).replace('@ver@', bt2_version) | |
91 | ||
92 | # create and return an external link node | |
93 | node = docutils.nodes.reference(rawtext, link_text, internal=False, refuri=url) | |
94 | return [node], [] | |
95 | ||
96 | ||
97 | def _add_roles(app): | |
98 | # add the extension's roles; the role functions above expect the | |
99 | # project's version as their first parameter | |
100 | app.add_role('bt2man', functools.partial(_bt2man_role, app.config.version)) | |
101 | app.add_role('bt2link', functools.partial(_bt2link_role, app.config.version)) | |
102 | ||
103 | ||
104 | def setup(app): | |
105 | app.connect('builder-inited', _add_roles) | |
106 | return { | |
107 | 'version': app.config.version, | |
108 | 'parallel_read_safe': True, | |
109 | } |