Skip to content

Commit 0b73119

Browse files
committed
- add support for paramlinks to be searchable, included in the index
1 parent 80e0d42 commit 0b73119

File tree

3 files changed

+82
-22
lines changed

3 files changed

+82
-22
lines changed

README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ Features
4646
lookup, using the ``:obj:`` role; then the parameter name is applied separately
4747
to produce the final reference link.
4848

49+
* The paramlinks are also added to the master index as well as the list
50+
of domain objects, which allows them to be searchable through the
51+
searchindex.js system. (new in 0.3.0)
4952

5053
Compatibility
5154
=============

sphinx_paramlinks/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
__version__ = '0.2.2'
1+
__version__ = '0.3.0'
22

3-
from .sphinx_paramlinks import setup
3+
from .sphinx_paramlinks import setup # noqa

sphinx_paramlinks/sphinx_paramlinks.py

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,61 @@
66
from sphinx.util.osutil import copyfile
77
from sphinx.util.console import bold
88
from sphinx.domains.python import PyXRefRole
9+
from sphinx.domains.python import PythonDomain
10+
11+
# the searchindex.js system relies upon the object types
12+
# in the PythonDomain to create search entries
13+
from sphinx.domains import ObjType
14+
15+
PythonDomain.object_types['parameter'] = ObjType('parameter', 'param')
16+
917

1018
def _is_html(app):
11-
return app.builder.name in ('html', 'readthedocs') # 'readthedocs', classy
19+
return app.builder.name in ('html', 'readthedocs')
20+
21+
22+
def _tempdata(app):
23+
if '_sphinx_paramlinks_index' in app.env.indexentries:
24+
idx = app.env.indexentries['_sphinx_paramlinks_index']
25+
else:
26+
app.env.indexentries['_sphinx_paramlinks_index'] = idx = {}
27+
return idx
28+
1229

1330
def autodoc_process_docstring(app, what, name, obj, options, lines):
1431
# locate :param: lines within docstrings. augment the parameter
1532
# name with that of the parent object name plus a token we can
16-
# spot later.
33+
# spot later. Also put an index entry in a temporary collection.
34+
35+
idx = _tempdata(app)
36+
37+
docname = app.env.temp_data['docname']
38+
if docname in idx:
39+
doc_idx = idx[docname]
40+
else:
41+
idx[docname] = doc_idx = []
42+
1743
def _cvt_param(name, line):
1844
if name.endswith(".__init__"):
1945
# kill off __init__ if present, the links are always
2046
# off the class
2147
name = name[0:-9]
48+
2249
def cvt(m):
50+
modifier, objname, paramname = m.group(1) or '', name, m.group(2)
51+
doc_idx.append(
52+
('single', '%s (%s parameter)' % (paramname, objname),
53+
'%s.params.%s' % (objname, paramname), '')
54+
)
55+
2356
return ":param %s_sphinx_paramlinks_%s.%s:" % (
24-
m.group(1) or '', name, m.group(2))
57+
modifier, objname, paramname)
2558
return re.sub(r'^:param ([^:]+? )?([^:]+?):', cvt, line)
2659

2760
if what in ('function', 'method', 'class'):
2861
lines[:] = [_cvt_param(name, line) for line in lines]
2962

63+
3064
class LinkParams(Transform):
3165
# apply references targets and optional references
3266
# to nodes that contain our target text.
@@ -52,7 +86,8 @@ def apply(self):
5286
refname = eq_match.group(1)
5387

5488
refid = "%s.params.%s" % (location, refname)
55-
ref.parent.insert(0,
89+
ref.parent.insert(
90+
0,
5691
nodes.target('', '', ids=[refid])
5792
)
5893
del ref[0]
@@ -77,23 +112,26 @@ def apply(self):
77112

78113
for pos, node in enumerate(ref.parent.children):
79114
# try to figure out where the node with the
80-
# paramname is. thought this was simple, but readthedocs
81-
# proving..it's not.
115+
# paramname is. thought this was simple, but
116+
# readthedocs proving..it's not.
82117
# TODO: need to take into account a type name
83118
# with the parens.
84-
if isinstance(node, nodes.TextElement) and node.astext() == paramname:
119+
if isinstance(node, nodes.TextElement) and \
120+
node.astext() == paramname:
85121
break
86122
else:
87123
return
88124

89-
ref.parent.insert(pos + 1,
90-
nodes.reference('', '',
91-
nodes.Text(u"¶", u"¶"),
92-
refid=refid,
93-
# paramlink is our own CSS class, headerlink
94-
# is theirs. Trying to get everything we can for existing
95-
# symbols...
96-
classes=['paramlink', 'headerlink']
125+
ref.parent.insert(
126+
pos + 1,
127+
nodes.reference(
128+
'', '',
129+
nodes.Text(u"¶", u"¶"),
130+
refid=refid,
131+
# paramlink is our own CSS class, headerlink
132+
# is theirs. Trying to get everything we can for
133+
# existing symbols...
134+
classes=['paramlink', 'headerlink']
97135
)
98136
)
99137

@@ -114,7 +152,8 @@ def lookup_params(app, env, node, contnode):
114152
resolve_target = ".".join(tokens[0:-1])
115153
paramname = tokens[-1]
116154

117-
# emulate the approach within sphinx.environment.BuildEnvironment.resolve_references
155+
# emulate the approach within
156+
# sphinx.environment.BuildEnvironment.resolve_references
118157
try:
119158
domain = env.domains[node['refdomain']] # hint: this will be 'py'
120159
except KeyError:
@@ -130,8 +169,9 @@ def lookup_params(app, env, node, contnode):
130169
# along with the classname/methodname/funcname minus the parameter
131170
# part.
132171

133-
newnode = domain.resolve_xref(env, refdoc, app.builder,
134-
"obj", resolve_target, node, contnode)
172+
newnode = domain.resolve_xref(
173+
env, refdoc, app.builder,
174+
"obj", resolve_target, node, contnode)
135175

136176
if newnode is not None:
137177
# assuming we found it, tack the paramname back onto to the final
@@ -142,11 +182,14 @@ def lookup_params(app, env, node, contnode):
142182
newnode['refid'] += ".params." + paramname
143183
return newnode
144184

185+
145186
def add_stylesheet(app):
146187
app.add_stylesheet('sphinx_paramlinks.css')
147188

189+
148190
def copy_stylesheet(app, exception):
149-
app.info(bold('The name of the builder is: %s' % app.builder.name), nonl=True)
191+
app.info(
192+
bold('The name of the builder is: %s' % app.builder.name), nonl=True)
150193

151194
if not _is_html(app) or exception:
152195
return
@@ -162,6 +205,20 @@ def copy_stylesheet(app, exception):
162205
copyfile(os.path.join(source, "sphinx_paramlinks.css"), dest)
163206
app.info('done')
164207

208+
209+
def build_index(app, doctree):
210+
entries = _tempdata(app)
211+
212+
for docname in entries:
213+
doc_entries = entries[docname]
214+
app.env.indexentries[docname].extend(doc_entries)
215+
216+
for sing, desc, ref, extra in doc_entries:
217+
app.env.domains['py'].data['objects'][ref] = (docname, 'parameter')
218+
219+
app.env.indexentries.pop('_sphinx_paramlinks_index')
220+
221+
165222
def setup(app):
166223
app.add_transform(LinkParams)
167224

@@ -174,4 +231,4 @@ def setup(app):
174231
app.connect('builder-inited', add_stylesheet)
175232
app.connect('build-finished', copy_stylesheet)
176233
app.connect('missing-reference', lookup_params)
177-
234+
app.connect('doctree-read', build_index)

0 commit comments

Comments
 (0)