Skip to content

Commit bc92307

Browse files
krowvinCopilot
andauthored
Add documentation links to CLI Commands (#130)
This will make it so our RTD that are generated either automatically via CLI lib or through our custom docs will be included in the commands. We need only make sure the root command matches the file name i.e. `cwms-cli blob` matches `blob.rst` in the docs Looks like this: ```bash cwms-cli ``` <img width="868" height="92" alt="image" src="https://github.com/user-attachments/assets/246c9885-63cc-44b6-8aaa-48695fb0e5c9" /> and ```bash cwms-cli usgs ``` <img width="885" height="114" alt="image" src="https://github.com/user-attachments/assets/4b5dab9f-0d36-4201-8a4c-25c8dd961d97" /> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: krowvin <23619282+krowvin@users.noreply.github.com>
1 parent fbf7f71 commit bc92307

2 files changed

Lines changed: 59 additions & 5 deletions

File tree

cwmscli/utils/click_help.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
from __future__ import annotations
22

33
import sys
4+
from typing import Optional
45

56
import click
67

78
from cwmscli.utils import colors
89
from cwmscli.utils.version import get_cwms_cli_version
910

11+
DOCS_BASE_URL = "https://cwms-cli.readthedocs.io/en/latest"
12+
1013

1114
def _render_version_line(ctx: click.Context) -> str:
1215
# Match existing CLI color behavior: disable color for non-TTY, --no-color, or --log-file.
@@ -20,7 +23,41 @@ def _render_version_line(ctx: click.Context) -> str:
2023
return f"Version: {colors.c(get_cwms_cli_version(), 'cyan', bright=True)}"
2124

2225

23-
def _inject_version_line(help_text: str, ctx: click.Context) -> str:
26+
def _docs_url_for_context(ctx: click.Context) -> Optional[str]:
27+
# Show docs links only on command root pages:
28+
# - cwms-cli --help (depth 1)
29+
# - cwms-cli <top-level-command> --help (depth 2)
30+
depth = 0
31+
cur = ctx
32+
while cur is not None:
33+
depth += 1
34+
cur = cur.parent
35+
36+
if depth == 1:
37+
return f"{DOCS_BASE_URL}/cli.html"
38+
if depth != 2:
39+
return None
40+
41+
command = (ctx.info_name or getattr(ctx.command, "name", None) or "").strip()
42+
page_map = {
43+
"blob": "blob",
44+
}
45+
# Link to dedicated pages that are created in \docs
46+
if command in page_map:
47+
return f"{DOCS_BASE_URL}/cli/{page_map[command]}.html"
48+
49+
# Fallback to the root CLI page with command anchor.
50+
return f"{DOCS_BASE_URL}/cli.html#cwms-cli-{command}"
51+
52+
53+
def _render_docs_line(ctx: click.Context) -> Optional[str]:
54+
docs_url = _docs_url_for_context(ctx)
55+
if docs_url is None:
56+
return None
57+
return f"Docs: {colors.c(docs_url, 'blue', bright=True)}"
58+
59+
60+
def _inject_help_header(help_text: str, ctx: click.Context) -> str:
2461
lines = help_text.splitlines()
2562
if not lines:
2663
return help_text
@@ -30,24 +67,29 @@ def _inject_version_line(help_text: str, ctx: click.Context) -> str:
3067
return help_text
3168

3269
version_line = _render_version_line(ctx)
70+
docs_line = _render_docs_line(ctx)
3371
if lines[0].startswith("Usage:"):
3472
lines.insert(1, version_line)
73+
if docs_line is not None:
74+
lines.insert(2, docs_line)
3575
else:
3676
lines.insert(0, version_line)
77+
if docs_line is not None:
78+
lines.insert(1, docs_line)
3779
return "\n".join(lines)
3880

3981

4082
def _wrap_get_help(command: click.Command) -> None:
4183
original_get_help = command.get_help
4284

43-
def get_help_with_version(ctx: click.Context) -> str:
44-
return _inject_version_line(original_get_help(ctx), ctx)
85+
def get_help_with_header(ctx: click.Context) -> str:
86+
return _inject_help_header(original_get_help(ctx), ctx)
4587

46-
command.get_help = get_help_with_version # type: ignore[method-assign]
88+
command.get_help = get_help_with_header # type: ignore[method-assign]
4789

4890

4991
def add_version_to_help_tree(command: click.Command) -> None:
50-
"""Patch a command tree so every help output shows the CLI version."""
92+
"""Patch a command tree so every help output shows the CLI version and docs link."""
5193
stack = [command]
5294
seen: set[int] = set()
5395

tests/cli/test_all_commands_help.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from click.testing import CliRunner
33

44
from cwmscli.__main__ import cli
5+
from cwmscli.utils.click_help import DOCS_BASE_URL
56
from cwmscli.utils.version import get_cwms_cli_version
67

78
## Expectations
@@ -37,6 +38,7 @@ def test_root_help(runner):
3738
assert result.exit_code == 0
3839
assert "Usage:" in result.output
3940
assert f"Version: {get_cwms_cli_version()}" in result.output
41+
assert f"Docs: {DOCS_BASE_URL}/cli.html" in result.output
4042

4143

4244
def test_root_version_flag(runner):
@@ -62,3 +64,13 @@ def test_every_command_has_help(runner, path, command):
6264
assert result.exit_code == 0, f"Failed on: {' '.join(args)}"
6365
assert "Usage:" in result.output
6466
assert f"Version: {get_cwms_cli_version()}" in result.output
67+
if len(path) == 1:
68+
page_map = {
69+
"blob": f"{DOCS_BASE_URL}/cli/blob.html",
70+
}
71+
expected_docs = page_map.get(
72+
path[0], f"{DOCS_BASE_URL}/cli.html#cwms-cli-{path[0]}"
73+
)
74+
assert f"Docs: {expected_docs}" in result.output
75+
else:
76+
assert "Docs:" not in result.output

0 commit comments

Comments
 (0)