1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
from collections import defaultdict
from operator import itemgetter
import re
from sphinx import addnodes
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, Index
from sphinx.roles import XRefRole
from sphinx.util.nodes import make_refnode
# Reference:
# https://www.sphinx-doc.org/en/master/development/tutorials/todo.html
# https://www.sphinx-doc.org/en/master/development/tutorials/recipe.html
class OptionDirective(ObjectDescription):
has_content = True
def handle_signature(self, sig, signode):
signode += addnodes.desc_name(text=sig)
return sig
def add_target_and_index(self, name_cls, sig, signode):
m = re.match(r'^--([^= ]+)', sig)
if not m:
raise Exception('option must start with --')
option_name = m.group(1)
signode['ids'].append(f'option-{option_name}')
qpdf = self.env.get_domain('qpdf')
qpdf.add_option(sig, option_name)
class OptionIndex(Index):
name = 'options'
localname = 'qpdf Command-line Options'
shortname = 'Options'
def generate(self, docnames=None):
content = defaultdict(list)
options = self.domain.get_objects()
options = sorted(options, key=itemgetter(0))
# name, subtype, docname, anchor, extra, qualifier, description
for name, display_name, typ, docname, anchor, _ in options:
m = re.match(r'^(--([^= ]+))', display_name)
if not m:
raise Exception(
'OptionIndex.generate: display name not as expected')
content[m.group(2)[0].lower()].append(
(m.group(1), 0, docname, anchor, '', '', typ))
content = sorted(content.items())
return content, True
class QpdfDomain(Domain):
name = 'qpdf'
label = 'qpdf documentation domain'
roles = {
'ref': XRefRole()
}
directives = {
'option': OptionDirective,
}
indices = {
OptionIndex,
}
initial_data = {
'options': [], # object list
}
def get_full_qualified_name(self, node):
return '{}.{}'.format('option', node.arguments[0])
def get_objects(self):
for obj in self.data['options']:
yield(obj)
def resolve_xref(self, env, from_doc_name, builder, typ, target, node,
contnode):
match = [(docname, anchor)
for name, sig, typ, docname, anchor, priority
in self.get_objects() if name == f'option.{target[2:]}']
if len(match) > 0:
to_doc_name = match[0][0]
match_target = match[0][1]
return make_refnode(builder, from_doc_name, to_doc_name,
match_target, contnode, match_target)
else:
raise Exception(f'invalid option xref ({target})')
def add_option(self, signature, option_name):
if self.env.docname != 'cli':
raise Exception(
'qpdf:option directives don\'t work outside of cli.rst')
name = f'option.{option_name}'
anchor = f'option-{option_name}'
# name, display_name, type, docname, anchor, priority
self.data['options'].append(
(name, signature, '', self.env.docname, anchor, 0))
def purge_options(self, docname):
self.data['options'] = list([
x for x in self.data['options']
if x[3] != docname
])
def purge_options(app, env, docname):
option = env.get_domain('qpdf')
option.purge_options(docname)
def setup(app):
app.add_domain(QpdfDomain)
app.connect('env-purge-doc', purge_options)
return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
|