diff --git a/craft_cli/helptexts.py b/craft_cli/helptexts.py index eabf4ac..4b7b6e4 100644 --- a/craft_cli/helptexts.py +++ b/craft_cli/helptexts.py @@ -68,9 +68,11 @@ def _build_item_plain(title: str, text: str, title_space: int) -> list[str]: text_space = TERMINAL_WIDTH - title_space - not_title_space wrapped_lines = textwrap.wrap(text, text_space) + result: list[str] = [] # first line goes with the title at column 4 - first = f" {title:>{title_space}s}: {wrapped_lines[0]}" - result = [first] + if wrapped_lines: + first = f" {title:>{title_space}s}: {wrapped_lines[0]}" + result.append(first) # the rest (if any) still aligned but without title for line in wrapped_lines[1:]: @@ -339,7 +341,9 @@ def _build_plain_command_help( positional_args_lines = ["Positional arguments:"] for title, text in parameters: positional_args_lines.extend(_build_item_plain(title, text, max_title_len)) - textblocks.append("\n".join(positional_args_lines)) + # Only populate if we have collected parameters. + if len(positional_args_lines) > 1: + textblocks.append("\n".join(positional_args_lines)) # command options option_lines = ["Options:"] @@ -401,10 +405,14 @@ def _build_markdown_command_help( "| | |", "|-|-|", ] - for title, text in parameters: + # Only keep items that have text + for title, text in ((title, text) for title, text in parameters if text): parameters_lines.append(f"| `{title}` | {text} |") - textblocks.append("\n".join(parameters_lines)) + # Only populate if we have collected parameters + # The header is 3 lines + if len(parameters_lines) > 3: + textblocks.append("\n".join(parameters_lines)) option_lines = [ "## Options:", diff --git a/tests/unit/test_help.py b/tests/unit/test_help.py index 204b655..c68dfaa 100644 --- a/tests/unit/test_help.py +++ b/tests/unit/test_help.py @@ -591,6 +591,82 @@ def test_command_help_text_with_parameters(docs_url, output_format): assert text == (expected_plain if output_format == OutputFormat.plain else expected_markdown) +@pytest.mark.parametrize("output_format", list(OutputFormat)) +def test_command_help_text_with_parameters_with_no_help(docs_url, output_format): + """Test help text for a command with parameters but no help.""" + overview = textwrap.dedent( + """ + Quite some long text. + """ + ) + cmd1 = create_command("somecommand", "Command one line help.", overview=overview) + cmd2 = create_command("other-cmd-2", "Some help.") + command_groups = [ + CommandGroup("group1", [cmd1, cmd2]), + ] + + options = [ + ("-h, --help", "Show this help message and exit."), + ("name", ""), + ("--revision", "The revision to release (defaults to latest)."), + ("extraparam", ""), + ("--other-option", "Other option."), + ("--experimental-1", HIDDEN), + ("--experimental-2", argparse.SUPPRESS), + ] + + help_builder = HelpBuilder("testapp", "general summary", command_groups, docs_url) + text = help_builder.get_command_help(cmd1(None), options, output_format) + + expected_plain = textwrap.dedent( + """\ + Usage: + testapp somecommand [options] + + Summary: + Quite some long text. + + Options: + -h, --help: Show this help message and exit. + --revision: The revision to release (defaults to latest). + --other-option: Other option. + + See also: + other-cmd-2 + + For a summary of all commands, run 'testapp help --all'. + """ + ) + if docs_url: + expected_plain += ( + "For more information, check out: " + "www.craft-app.com/docs/3.14159/reference/commands/somecommand\n" + ) + expected_markdown = textwrap.dedent( + """\ + ## Usage: + ```text + testapp somecommand [options] + ``` + + ## Summary: + + Quite some long text. + + ## Options: + | | | + |-|-| + | `-h, --help` | Show this help message and exit. | + | `--revision` | The revision to release (defaults to latest). | + | `--other-option` | Other option. | + + ## See also: + - `other-cmd-2` + """ + ) + assert text == (expected_plain if output_format == OutputFormat.plain else expected_markdown) + + @pytest.mark.parametrize("output_format", list(OutputFormat)) def test_command_help_text_complex_overview(docs_url, output_format): """The overviews are processed in different ways."""