Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
- Fix Sphinx warnings about parallel reads.
- Add `force_args_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.

## 1.13.1

Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,23 @@ With `sphinx_argparse_cli_prefix_document = True` (anchors prefixed by document

The anchor text is visible after the `#` in the URL when you click a heading.

Flags and positional arguments are also registered as Sphinx program options, so the `:option:` role works with the
program (and sub-command) name followed by the argument, or scoped through a `.. program::` directive:

```rst
:option:`tox --magic`
:option:`tox run --magic`

.. program:: tox run

:option:`--magic`
:option:`--magic=value`
```

`:option:` targets keep their original case, so they do not need `:force_refs_lower:`. They ignore
`sphinx_argparse_cli_prefix_document`; when two documents render the same program, the role links to the first one
Sphinx reads.

### Handle mixed-case references

Sphinx `:ref:` only supports lower-case targets. When your program name or flags contain capital letters, set
Expand Down
8 changes: 8 additions & 0 deletions roots/test-option/conf.py
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions roots/test-option/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. sphinx_argparse_cli::
:module: parser
:func: make

Option role test
----------------
Flag :option:`prog --root`, alias :option:`prog -r`, sub-command :option:`prog run --magic`, positional
:option:`prog run target`.

.. program:: prog run

Scoped :option:`--magic` and :option:`--magic=value`.
12 changes: 12 additions & 0 deletions roots/test-option/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from __future__ import annotations

from argparse import ArgumentParser


def make() -> ArgumentParser:
parser = ArgumentParser(description="argparse tester", prog="prog")
parser.add_argument("--root", "-r", action="store_true", help="root flag")
run = parser.add_subparsers().add_parser("run", help="run it")
run.add_argument("target")
run.add_argument("--magic", help="magic")
return parser
2 changes: 2 additions & 0 deletions src/sphinx_argparse_cli/_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from docutils.parsers.rst.directives import flag, positive_int, unchanged, unchanged_required
from docutils.statemachine import StringList
from sphinx.locale import __
from sphinx.util import ws_re
from sphinx.util.docutils import SphinxDirective
from sphinx.util.logging import getLogger

Expand Down Expand Up @@ -281,6 +282,7 @@ def _mk_option_name(self, line: paragraph, prefix: str, opt: str) -> None:
line.attributes["ids"].append(ref_id)
ref += strong("", "", literal(text=opt))
self._register_ref(ref_id, ref_title, ref, is_cli_option=True)
self._std_domain.add_program_option(ws_re.sub("-", prefix), opt, self.env.docname, ref_id)
line += ref

def _register_ref(
Expand Down
15 changes: 15 additions & 0 deletions tests/test_logic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import os
import re
import sys
from pathlib import Path
from typing import TYPE_CHECKING
Expand Down Expand Up @@ -215,6 +216,20 @@ def test_ref_prefix_doc(build_outcome: str) -> None:
assert ref in build_outcome


@pytest.mark.sphinx(buildername="html", testroot="option")
def test_option_role_as_html(build_outcome: str, warning: StringIO) -> None:
hrefs = re.findall(r'<a class="reference internal" href="(#[^"]+)"><code class="xref std std-option', build_outcome)
assert hrefs == [
"#prog---root",
"#prog--r",
"#prog-run---magic",
"#prog-run-target",
"#prog-run---magic",
"#prog-run---magic",
]
assert not warning.getvalue()


@pytest.mark.sphinx(buildername="text", testroot="ref-duplicate-label")
def test_ref_duplicate_label(build_outcome: tuple[str, str], warning: StringIO) -> None:
assert build_outcome
Expand Down