diff --git a/CHANGELOG.md b/CHANGELOG.md index cb681d9..df85f2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file. - Add `force_refs_lower` to enable `:ref:` links with mixed-case program names and arguments. - Fix Sphinx smart quotes rewriting `--` to an en dash in `--option` names within descriptions, epilogs, and help text. - Register flags and positional arguments as Sphinx program options so the `:option:` role links to them. +- Leave apostrophes inside words (`don't`, `it's`) alone in help text instead of turning them into broken inline + literals. ## 1.13.1 diff --git a/roots/test-help-apostrophe/conf.py b/roots/test-help-apostrophe/conf.py new file mode 100644 index 0000000..9f2a54a --- /dev/null +++ b/roots/test-help-apostrophe/conf.py @@ -0,0 +1,8 @@ +from __future__ import annotations + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +extensions = ["sphinx_argparse_cli"] +nitpicky = True diff --git a/roots/test-help-apostrophe/index.rst b/roots/test-help-apostrophe/index.rst new file mode 100644 index 0000000..708ad9c --- /dev/null +++ b/roots/test-help-apostrophe/index.rst @@ -0,0 +1,3 @@ +.. sphinx_argparse_cli:: + :module: parser + :func: make diff --git a/roots/test-help-apostrophe/parser.py b/roots/test-help-apostrophe/parser.py new file mode 100644 index 0000000..50068d2 --- /dev/null +++ b/roots/test-help-apostrophe/parser.py @@ -0,0 +1,10 @@ +from __future__ import annotations + +from argparse import ArgumentParser + + +def make() -> ArgumentParser: + parser = ArgumentParser(prog="prog", add_help=False) + parser.add_argument("--a", help="don't use it's value") + parser.add_argument("--b", help="it's a 'thing' to see") + return parser diff --git a/src/sphinx_argparse_cli/_logic.py b/src/sphinx_argparse_cli/_logic.py index 21f3bef..c655bb7 100644 --- a/src/sphinx_argparse_cli/_logic.py +++ b/src/sphinx_argparse_cli/_logic.py @@ -411,8 +411,9 @@ def make_id(key: str) -> str: _HELP_SUBSTITUTIONS: Final[list[tuple[re.Pattern[str], str]]] = [ - (re.compile(r"[']+(.+?)[']+"), "``'\\1'``"), - (re.compile(r'["]+(.+?)["]+'), '``"\\1"``'), + # a quote glued to a word character is an apostrophe (don't, it's), not the edge of a quoted span + (re.compile(r"(? None: assert "complex first [-h]" in build_outcome.split("a-first-desc", maxsplit=1)[0] +@pytest.mark.sphinx(buildername="text", testroot="help-apostrophe") +def test_help_apostrophe(build_outcome: str, warning: StringIO) -> None: + assert ( + build_outcome + == """prog - CLI interface +******************** + + prog [--a A] [--b B] + + +prog options +============ + +* **"--a"** "A" - don't use it's value + +* **"--b"** "B" - it's a "'thing'" to see +""" + ) + assert not warning.getvalue() + + @pytest.mark.sphinx(buildername="text", testroot="suppressed-action") def test_suppressed_action(build_outcome: str) -> None: assert "--activities-since" not in build_outcome @@ -183,13 +204,17 @@ def test_suppressed_action(build_outcome: str) -> None: @pytest.mark.parametrize( ("example", "output"), [ - ("", ""), - ("{", "{"), - ('"', '"'), - ("'", "'"), - ("{a}", "``{a}``"), - ('"a"', '``"a"``'), - ("'a'", "``'a'``"), + pytest.param("", "", id="empty"), + pytest.param("{", "{", id="lone-brace"), + pytest.param('"', '"', id="lone-double-quote"), + pytest.param("'", "'", id="lone-single-quote"), + pytest.param("{a}", "``{a}``", id="braces"), + pytest.param('"a"', '``"a"``', id="double-quoted"), + pytest.param("'a'", "``'a'``", id="single-quoted"), + pytest.param("don't use it's value", "don't use it's value", id="apostrophes"), + pytest.param("it's a 'thing' to see", "it's a ``'thing'`` to see", id="apostrophe-and-quoted"), + pytest.param("'a' and 'b'", "``'a'`` and ``'b'``", id="two-quoted"), + pytest.param('say "hi" or "bye"', 'say ``"hi"`` or ``"bye"``', id="two-double-quoted"), ], ) def test_help_loader(example: str, output: str) -> None: