Skip to content

Commit 4f84d6d

Browse files
committed
doc: links to doc for cadscript methods in example source code
1 parent d2ab7dc commit 4f84d6d

File tree

5 files changed

+86
-35
lines changed

5 files changed

+86
-35
lines changed

docs/ext/cadscript_directives.py

+79-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from cadquery.occ_impl.assembly import toJSON
1313
from cadquery.occ_impl.jupyter_tools import DEFAULT_COLOR
1414
from docutils.parsers.rst import directives
15+
from sphinx.application import Sphinx
1516

1617
from cadquery.cq_directive import cq_directive_vtk, template_vtk, rendering_code
1718

@@ -45,6 +46,8 @@
4546
4647
"""
4748

49+
theapp = None
50+
4851

4952
class cadscript_directive(cq_directive_vtk):
5053

@@ -90,7 +93,7 @@ def run(self):
9093
pre_script, script, text = self.get_source_file(content, options.get("steps", None), "text_from_comment" in options)
9194
else:
9295
# else use inline code
93-
script = "\n".join(script)
96+
script = "\n".join(script)
9497

9598
# add the prefix and postfix
9699
plot_code = prefix + "\n" + pre_script + "\n" + script + "\n" + postfix.format(result_var=result_var)
@@ -174,9 +177,7 @@ def generate_output(self, plot_code, text, script, options):
174177
lines.append(" <div class=\"cq-top-bottom\"><div class=\"cq-top\">")
175178
lines.append("")
176179

177-
lines.extend(["", "::", ""])
178-
lines.extend([" %s" % row.rstrip() for row in script.split("\n")])
179-
lines.append("")
180+
lines.extend(self.generate_code_block(script))
180181

181182
lines.append(".. raw:: html")
182183
lines.append("")
@@ -294,6 +295,74 @@ def render_image(self, assy, options):
294295
).splitlines()
295296

296297

298+
def generate_code_block(self, code):
299+
"""
300+
Generate a code block with links to the documentation for method calls.
301+
"""
302+
highlighter = theapp.builder.highlighter
303+
304+
body_prefixes = ["body", "box", "result", "extr"]
305+
sketch_prefixes = ["sketch", "s"]
306+
cadscript_prefixes = ["cad", "cadscript"]
307+
308+
# Regular expression to find method calls like obj.method(
309+
# in html the string looks like
310+
# <span class="n">cadscript</span><span class="o">.</span><span class="n">make_box</span><span class="p">(
311+
312+
method_call_pattern = re.compile(
313+
r'\<span\s+class\=\"n\"\>' # <span class="n">
314+
r'\s*(\w+)\s*' # methodName
315+
r'\<\/span\>\s*' # </span>
316+
r'\<span\s+class\=\"o\"\>' # <span class="o">
317+
r'\s*\.\s*' # .
318+
r'\<\/span\>\s*' # </span>
319+
r'\<span\s+class\=\"n\"\>' # <span class="n">
320+
r'\s*(\w+)\s*' # methodName
321+
r'\<\/span\>\s*' # </span>
322+
r'\<span\s+class\=\"p\"\>' # <span class="p">
323+
r'\s*\(' # (
324+
)
325+
326+
# Function to replace method calls with links if they are documented
327+
# class="n">(\w+)\.(\w+)\((.*?)\)')
328+
def replace_method_call(match):
329+
obj_name, method_name = match.groups()
330+
331+
# Determine which document to link based on the prefix
332+
# todo: could be done by examining env.domaindata['py']['objects']
333+
if any(obj_name.startswith(prefix) for prefix in body_prefixes):
334+
link_target = f'ref_body.html#cadscript.Body.{method_name}'
335+
elif any(obj_name.startswith(prefix) for prefix in sketch_prefixes):
336+
link_target = f'ref_sketch.html#cadscript.Sketch.{method_name}'
337+
elif any(obj_name.startswith(prefix) for prefix in cadscript_prefixes):
338+
link_target = f'ref_module_functions.html#cadscript.{method_name}'
339+
else:
340+
return match.group(0) # No replacement if prefix does not match
341+
342+
link = (
343+
f'<span class="n">{obj_name}</span>'
344+
f'<span class="o">.</span>'
345+
f'<span class="n"><a class="codelink" href="{link_target}">{method_name}</a></span>'
346+
f'<span class="p">('
347+
)
348+
return link
349+
350+
351+
# Use Sphinx highlighter to generate HTML
352+
highlighted_code = highlighter.highlight_block(code, 'python')
353+
354+
# Replace method calls with links
355+
linked_code = method_call_pattern.sub(replace_method_call, highlighted_code)
356+
357+
lines = []
358+
lines.append(".. raw:: html")
359+
lines.append("")
360+
lines.extend([" %s" % line.rstrip() for line in linked_code.split("\n")])
361+
lines.append("")
362+
363+
return lines
364+
365+
297366

298367
class cadscript_auto_directive(cadscript_directive):
299368

@@ -355,6 +424,12 @@ def setup(app):
355424
app.add_js_file("vtk.js")
356425
app.add_js_file(None, body=rendering_code)
357426

427+
app.connect("builder-inited", remember_app)
428+
429+
430+
def remember_app(app: Sphinx) -> None:
431+
global theapp # bad hack to remember the app object
432+
theapp = app
358433

359434

360435
if __name__ == "__main__":

docs/source/_static/cadscript.css

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ div.cq-side-by-side {
1919
/* cq render after code */
2020

2121

22-
div.cq-top > div.highlight-default { /* code block */
22+
div.cq-top > div.highlight { /* code block */
2323
margin-bottom: 0;
2424
border-left: 5px solid #ccc;
2525
}
@@ -36,4 +36,8 @@ table.docutils td p {
3636
text-wrap: wrap;
3737
}
3838

39-
39+
/* links in code */
40+
a.codelink, a.codelink:visited {
41+
color: #0000FF;
42+
text-decoration: underline #C0C0FF;
43+
}

docs/source/doc_sketch_examples.rst

-15
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@ Rectangles
4141

4242

4343

44-
See also
45-
46-
.. hlist::
47-
48-
* :py:meth:`cadscript.make_box`
49-
* :py:meth:`Sketch.add_rect`
50-
51-
52-
5344
Circles
5445
-------
5546

@@ -74,10 +65,4 @@ Circles
7465
sketch.add_circle(d=40, pos=(20, 10))
7566

7667

77-
See also
78-
79-
.. hlist::
80-
81-
* :py:meth:`cadscript.make_box`
82-
* :py:meth:`Sketch.add_circle`
8368

docs/source/intro_getting_started.rst

-12
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,6 @@ Finally, we place the sketch on the top face of our object, rotate it 45 degrees
5252
.. cadscript::
5353
:source: ../examples/getting_started.py
5454

55-
.. topic:: Api References
56-
57-
.. hlist::
58-
59-
* :py:meth:`cadscript.make_box`
60-
* :py:meth:`Body.fillet`
61-
* :py:meth:`Body.chamfer`
62-
* :py:meth:`cadscript.make_sketch`
63-
* :py:meth:`Sketch.add_circle`
64-
* :py:meth:`Sketch.add_rect`
65-
* :py:meth:`Body.cut_extrude`
66-
6755

6856
Second Example
6957
--------------

examples/bracket.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,4 @@
100100

101101
# STEP 14 dummy step to show whole script in documentation
102102
# The complete script looks like this:
103-
104-
cadscript.show(result)
103+
cadscript.show(result)

0 commit comments

Comments
 (0)