Skip to content

Commit a8ad42a

Browse files
authored
šŸ› fix(render): handle formatter subclasses and wrap preformatted blocks (#297)
1 parent 9533451 commit a8ad42a

6 files changed

Lines changed: 60 additions & 3 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from __future__ import annotations
2+
3+
import sys
4+
from pathlib import Path
5+
6+
sys.path.insert(0, str(Path(__file__).parent))
7+
extensions = ["sphinx_argparse_cli"]
8+
nitpicky = True
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.. sphinx_argparse_cli::
2+
:module: parser
3+
:func: make
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from __future__ import annotations
2+
3+
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, RawDescriptionHelpFormatter
4+
5+
6+
class _Formatter(ArgumentDefaultsHelpFormatter, RawDescriptionHelpFormatter): ...
7+
8+
9+
def make() -> ArgumentParser:
10+
return ArgumentParser(
11+
prog="foo",
12+
epilog="""This epilog
13+
spans multiple lines.
14+
15+
this line is indented.
16+
and also this.
17+
18+
Now this should be a separate paragraph.
19+
""",
20+
formatter_class=_Formatter,
21+
add_help=False,
22+
)

ā€Žsrc/sphinx_argparse_cli/__init__.pyā€Ž

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,24 @@ def setup(app: Sphinx) -> dict[str, Any]:
1515

1616
app.add_directive(SphinxArgparseCli.name, SphinxArgparseCli)
1717
app.add_config_value("sphinx_argparse_cli_prefix_document", False, "env") # noqa: FBT003
18+
app.add_css_file("sphinx_argparse_cli.css")
19+
app.connect("build-finished", _write_css)
1820

1921
return {"parallel_read_safe": True}
2022

2123

24+
def _write_css(app: Sphinx, exception: Exception | None) -> None:
25+
if exception or not app.builder or app.builder.format != "html":
26+
return
27+
from pathlib import Path # noqa: PLC0415
28+
29+
static = Path(app.outdir) / "_static"
30+
static.mkdir(parents=True, exist_ok=True)
31+
(static / "sphinx_argparse_cli.css").write_text(
32+
".sphinx-argparse-cli-wrap pre { white-space: pre-wrap; word-wrap: break-word; }\n"
33+
)
34+
35+
2236
__all__ = [
2337
"__version__",
2438
]

ā€Žsrc/sphinx_argparse_cli/_logic.pyā€Ž

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ def parser(self) -> ArgumentParser:
145145
self._parser.prog = new_prog
146146
_update_sub_parser_prog(self._parser, old_prog, new_prog)
147147

148-
self._raw_format = self._parser.formatter_class == RawDescriptionHelpFormatter
148+
formatter = self._parser.formatter_class
149+
self._raw_format = isinstance(formatter, type) and issubclass(formatter, RawDescriptionHelpFormatter)
149150
return self._parser
150151

151152
def _load_sub_parsers(
@@ -224,7 +225,7 @@ def _pre_format(self, block: None | str) -> None | paragraph | literal_block:
224225
if block is None:
225226
return None
226227
if self._raw_format and "\n" in block:
227-
lit = literal_block("", Text(block))
228+
lit = literal_block("", Text(block), classes=["sphinx-argparse-cli-wrap"])
228229
lit["language"] = "none"
229230
return lit
230231
return paragraph("", Text(block))
@@ -424,7 +425,7 @@ def _mk_usage(self, parser: ArgumentParser) -> literal_block:
424425
with self.no_color():
425426
texts = parser.format_usage()[len("usage: ") :].splitlines()
426427
texts = [line if at == 0 else f"{' ' * (len(parser.prog) + 1)}{line.lstrip()}" for at, line in enumerate(texts)]
427-
return literal_block("", Text("\n".join(texts)))
428+
return literal_block("", Text("\n".join(texts)), classes=["sphinx-argparse-cli-wrap"])
428429

429430
@contextmanager
430431
def no_color(self) -> Iterator[None]:

ā€Žtests/test_logic.pyā€Ž

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ def test_multiline_epilog_as_html(build_outcome: str) -> None:
133133
assert ref in build_outcome
134134

135135

136+
@pytest.mark.sphinx(buildername="html", testroot="epilog-multiline-subclass")
137+
def test_multiline_epilog_subclass_formatter_as_html(build_outcome: str) -> None:
138+
ref = (
139+
"This epilog\nspans multiple lines.\n\n this line is indented.\n and also this.\n\nNow this should be"
140+
" a separate paragraph.\n"
141+
)
142+
assert ref in build_outcome
143+
144+
136145
@pytest.mark.sphinx(buildername="text", testroot="complex")
137146
@pytest.mark.prepare(directive_args=[":usage_width: 100"])
138147
def test_usage_width_default(build_outcome: str) -> None:

0 commit comments

Comments
Ā (0)