Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add documentation link in help messages #298

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 5 additions & 2 deletions craft_cli/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,19 +209,22 @@ class Dispatcher:
:param extra_global_args: other automatic global arguments than the ones
provided automatically
:param default_command: the command to run if none was specified in the command line
:param docs_base_url: The base address of the documentation, for help messages.
"""

def __init__(
def __init__( # noqa: PLR0913 (too-many-arguments)
self,
appname: str,
commands_groups: list[CommandGroup],
*,
summary: str = "",
extra_global_args: list[GlobalArgument] | None = None,
default_command: type[BaseCommand] | None = None,
docs_base_url: str | None = None,
) -> None:
self._default_command = default_command
self._help_builder = HelpBuilder(appname, summary, commands_groups)
self._docs_base_url = docs_base_url
self._help_builder = HelpBuilder(appname, summary, commands_groups, docs_base_url)

self.global_arguments = _DEFAULT_GLOBAL_ARGS[:]
if extra_global_args is not None:
Expand Down
62 changes: 46 additions & 16 deletions craft_cli/helptexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,25 @@ class HelpBuilder:
"""Produce the different help texts."""

def __init__(
self, appname: str, general_summary: str, command_groups: list[CommandGroup]
self,
appname: str,
general_summary: str,
command_groups: list[CommandGroup],
docs_base_url: str | None = None,
) -> None:
"""Initialize the help builder.

:param appname: The name of the application.
:param general_summary: A summary of the application.
:param command_groups: The CommandGroups for the application.
:param docs_base_url: The base URL for the documentation.
"""
self.appname = appname
self.general_summary = general_summary
self.command_groups = command_groups
self._docs_base_url = docs_base_url
if docs_base_url and docs_base_url.endswith("/"):
self._docs_base_url = docs_base_url[:-1]

def get_usage_message(self, error_message: str, command: str = "") -> str:
"""Build a usage and error message.
Expand Down Expand Up @@ -156,7 +170,7 @@ def get_full_help(self, global_options: list[tuple[str, str]]) -> str:
- summary
- common commands listed and described shortly
- all commands grouped, just listed
- more help
- more help and documentation
"""
textblocks = []

Expand Down Expand Up @@ -207,11 +221,17 @@ def get_full_help(self, global_options: list[tuple[str, str]]) -> str:
textwrap.dedent(
f"""
For more information about a command, run '{self.appname} help <command>'.
For a summary of all commands, run '{self.appname} help --all'.
"""
For a summary of all commands, run '{self.appname} help --all'."""
)
)

# append documentation links to block for more help
if self._docs_base_url:
textblocks[-1] += (
f"\nFor more information about {self.appname}, "
f"check out: {self._docs_base_url}"
)

# join all stripped blocks, leaving ONE empty blank line between
return "\n\n".join(block.strip() for block in textblocks) + "\n"

Expand All @@ -228,6 +248,7 @@ def get_detailed_help(self, global_options: list[tuple[str, str]]) -> str:
- global options
- all commands shown with description, grouped
- more help
- more help and documentation
mr-cal marked this conversation as resolved.
Show resolved Hide resolved
"""
textblocks = []

Expand Down Expand Up @@ -264,18 +285,24 @@ def get_detailed_help(self, global_options: list[tuple[str, str]]) -> str:
textblocks.append(
textwrap.dedent(
f"""
For more information about a specific command, run '{self.appname} help <command>'.
"""
For more information about a specific command, run '{self.appname} help <command>'."""
)
)

# append documentation links to block for more help
if self._docs_base_url:
textblocks[-1] += (
f"\nFor more information about {self.appname}, "
f"check out: {self._docs_base_url}"
)

# join all stripped blocks, leaving ONE empty blank line between
return "\n\n".join(block.strip() for block in textblocks) + "\n"

def _build_plain_command_help(
self,
command: BaseCommand,
usage: str,
overview: str,
parameters: list[tuple[str, str]],
options: list[tuple[str, str]],
other_command_names: list[str],
Expand All @@ -289,7 +316,7 @@ def _build_plain_command_help(
- positional arguments (only if parameters are not empty)
- options
- other related commands
- footer
- help for all commands and documentation
"""
textblocks = []

Expand All @@ -302,7 +329,7 @@ def _build_plain_command_help(
)
)

overview = textwrap.indent(overview, " ")
overview = textwrap.indent(command.overview, " ")
textblocks.append(f"Summary:{overview}")

# column alignment is dictated by longest options title
Expand All @@ -326,19 +353,23 @@ def _build_plain_command_help(
see_also_block.extend((" " + name) for name in sorted(other_command_names))
textblocks.append("\n".join(see_also_block))

# footer
# help for all commands
textblocks.append(
f"""
For a summary of all commands, run '{self.appname} help --all'.
"""
For a summary of all commands, run '{self.appname} help --all'."""
)

# documentation link
if self._docs_base_url:
command_url = f"{self._docs_base_url}/reference/commands/{command.name}"
tigarmo marked this conversation as resolved.
Show resolved Hide resolved
textblocks[-1] += f"\nFor more information, check out: {command_url}"
dariuszd21 marked this conversation as resolved.
Show resolved Hide resolved

return textblocks

def _build_markdown_command_help(
self,
command: BaseCommand,
usage: str,
overview: str,
parameters: list[tuple[str, str]],
options: list[tuple[str, str]],
other_command_names: list[str],
Expand All @@ -352,7 +383,6 @@ def _build_markdown_command_help(
- positional arguments (only if parameters are not empty)
- options
- other related commands
- footer
"""
textblocks = []

Expand All @@ -367,7 +397,7 @@ def _build_markdown_command_help(
)
)

overview = process_overview_for_markdown(overview)
overview = process_overview_for_markdown(command.overview)
textblocks.append(f"## Summary:\n\n{overview}")

if parameters:
Expand Down Expand Up @@ -444,7 +474,7 @@ def get_command_help(
builder = self._build_markdown_command_help
else:
builder = self._build_plain_command_help
textblocks = builder(usage, command.overview, parameters, options, other_command_names)
textblocks = builder(command, usage, parameters, options, other_command_names)

# join all stripped blocks, leaving ONE empty blank line between
return "\n\n".join(block.strip() for block in textblocks) + "\n"
9 changes: 7 additions & 2 deletions tests/unit/test_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,17 @@
# --- Tests for the Dispatcher


def test_dispatcher_help_init():
@pytest.mark.parametrize("docs_base_url", [None, "www.craft-app.com/docs/3.14159"])
def test_dispatcher_help_init(docs_base_url):
"""Init the help infrastructure properly."""
groups = [CommandGroup("title", [create_command("somecommand")])]
dispatcher = Dispatcher("test-appname", groups, summary="test summary")
dispatcher = Dispatcher(
"test-appname", groups, summary="test summary", docs_base_url=docs_base_url
)

assert dispatcher._help_builder.appname == "test-appname"
assert dispatcher._help_builder.general_summary == "test summary"
assert dispatcher._help_builder._docs_base_url == docs_base_url


def test_dispatcher_pre_parsing():
Expand Down
Loading
Loading