|
6 | 6 | import inspect |
7 | 7 | import os |
8 | 8 | import sys |
| 9 | +from typing import ClassVar |
9 | 10 |
|
10 | 11 | import tomli |
| 12 | +from docutils.parsers.rst import directives |
| 13 | +from sphinx.application import Sphinx |
| 14 | +from sphinx.directives.code import parse_line_num_spec |
| 15 | +from sphinx.ext.doctest import TestcodeDirective |
| 16 | +from sphinx.util.typing import OptionSpec |
11 | 17 |
|
12 | 18 | # -- Project information ----------------------------------------------------- |
13 | 19 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information |
|
40 | 46 | "sphinx.ext.intersphinx", |
41 | 47 | "myst_parser", # Enables markdown support |
42 | 48 | "sphinx_design", # Enables side to side cards |
| 49 | + "sphinx.ext.doctest", |
43 | 50 | ] |
44 | 51 |
|
45 | 52 | # -- Options for HTML output ------------------------------------------------- |
@@ -134,3 +141,37 @@ def _get_version_str() -> str: |
134 | 141 | except KeyError: |
135 | 142 | version_str = "main" |
136 | 143 | return version_str |
| 144 | + |
| 145 | + |
| 146 | +class _TestcodeWithEmphasisDirective(TestcodeDirective): |
| 147 | + """ |
| 148 | + Extension of ``.. testcode::`` that additionally supports ``:emphasize-lines:``. |
| 149 | +
|
| 150 | + Sphinx's built-in ``.. testcode::`` directive does not support ``:emphasize-lines:``. This |
| 151 | + subclass adds that option and forwards it as ``highlight_args['hl_lines']`` on the resulting |
| 152 | + node, which is the same mechanism used by ``.. code-block::``. |
| 153 | +
|
| 154 | + Ideally, this should be integrated to sphinx.ext.doctest as part of a solution to |
| 155 | + https://github.com/sphinx-doc/sphinx/issues/6915 and |
| 156 | + https://github.com/sphinx-doc/sphinx/issues/6858. |
| 157 | + """ |
| 158 | + |
| 159 | + option_spec: ClassVar[OptionSpec] = { |
| 160 | + **TestcodeDirective.option_spec, |
| 161 | + "emphasize-lines": directives.unchanged_required, |
| 162 | + } |
| 163 | + |
| 164 | + def run(self) -> list: |
| 165 | + result = super().run() |
| 166 | + linespec = self.options.get("emphasize-lines") |
| 167 | + if linespec and result: |
| 168 | + node = result[0] |
| 169 | + nlines = len(self.content) |
| 170 | + hl_lines = parse_line_num_spec(linespec, nlines) |
| 171 | + hl_lines = [x + 1 for x in hl_lines if x < nlines] |
| 172 | + node["highlight_args"] = {"hl_lines": hl_lines} |
| 173 | + return result |
| 174 | + |
| 175 | + |
| 176 | +def setup(app: Sphinx) -> None: |
| 177 | + app.add_directive("testcode", _TestcodeWithEmphasisDirective, override=True) |
0 commit comments