diff --git a/docs/tutorial/typer-command.md b/docs/tutorial/typer-command.md index 710115a749..021dee002d 100644 --- a/docs/tutorial/typer-command.md +++ b/docs/tutorial/typer-command.md @@ -272,6 +272,7 @@ $ typer some_script.py utils docs * `--name TEXT`: The name of the CLI program to use in docs. * `--output FILE`: An output file to write docs to, like README.md. +* `--title TEXT`: A title to use in the docs, by default the name of the command. For example: diff --git a/tests/assets/cli/multiapp-docs-title.md b/tests/assets/cli/multiapp-docs-title.md new file mode 100644 index 0000000000..e688a9ba91 --- /dev/null +++ b/tests/assets/cli/multiapp-docs-title.md @@ -0,0 +1,102 @@ +# Awesome CLI + +Demo App + +**Usage**: + +```console +$ multiapp [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--install-completion`: Install completion for the current shell. +* `--show-completion`: Show completion for the current shell, to copy it or customize the installation. +* `--help`: Show this message and exit. + +The end + +**Commands**: + +* `sub` +* `top`: Top command + +## `multiapp sub` + +**Usage**: + +```console +$ multiapp sub [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--help`: Show this message and exit. + +**Commands**: + +* `bye`: Say bye +* `hello`: Say Hello +* `hi`: Say Hi + +### `multiapp sub bye` + +Say bye + +**Usage**: + +```console +$ multiapp sub bye [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. + +### `multiapp sub hello` + +Say Hello + +**Usage**: + +```console +$ multiapp sub hello [OPTIONS] +``` + +**Options**: + +* `--name TEXT`: [default: World] +* `--age INTEGER`: The age of the user [default: 0] +* `--help`: Show this message and exit. + +### `multiapp sub hi` + +Say Hi + +**Usage**: + +```console +$ multiapp sub hi [OPTIONS] [USER] +``` + +**Arguments**: + +* `[USER]`: The name of the user to greet [default: World] + +**Options**: + +* `--help`: Show this message and exit. + +## `multiapp top` + +Top command + +**Usage**: + +```console +$ multiapp top [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. diff --git a/tests/test_cli/test_doc.py b/tests/test_cli/test_doc.py index 903c51ddec..98e30631ba 100644 --- a/tests/test_cli/test_doc.py +++ b/tests/test_cli/test_doc.py @@ -55,6 +55,36 @@ def test_doc_output(tmp_path: Path): assert "Docs saved to:" in result.stdout +def test_doc_title_output(tmp_path: Path): + out_file: Path = tmp_path / "out.md" + result = subprocess.run( + [ + sys.executable, + "-m", + "coverage", + "run", + "-m", + "typer", + "tests.assets.cli.multi_app", + "utils", + "docs", + "--name", + "multiapp", + "--title", + "Awesome CLI", + "--output", + str(out_file), + ], + capture_output=True, + encoding="utf-8", + ) + docs_path: Path = Path(__file__).parent.parent / "assets/cli/multiapp-docs-title.md" + docs = docs_path.read_text() + written_docs = out_file.read_text() + assert docs in written_docs + assert "Docs saved to:" in result.stdout + + def test_doc_not_existing(): result = subprocess.run( [ diff --git a/typer/cli.py b/typer/cli.py index 12a755de48..70b9101f37 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -189,12 +189,14 @@ def get_docs_for_click( indent: int = 0, name: str = "", call_prefix: str = "", + title: Optional[str] = None, ) -> str: docs = "#" * (1 + indent) command_name = name or obj.name if call_prefix: command_name = f"{call_prefix} {command_name}" - title = f"`{command_name}`" if command_name else "CLI" + if not title: + title = f"`{command_name}`" if command_name else "CLI" docs += f" {title}\n\n" if obj.help: docs += f"{obj.help}\n\n" @@ -264,12 +266,17 @@ def get_docs_for_click( def docs( ctx: typer.Context, name: str = typer.Option("", help="The name of the CLI program to use in docs."), - output: Path = typer.Option( + output: Optional[Path] = typer.Option( None, help="An output file to write docs to, like README.md.", file_okay=True, dir_okay=False, ), + title: Optional[str] = typer.Option( + None, + help="The title for the documentation page. If not provided, the name of " + "the program is used.", + ), ) -> None: """ Generate Markdown docs for a Typer app. @@ -279,7 +286,7 @@ def docs( typer.echo("No Typer app found", err=True) raise typer.Abort() click_obj = typer.main.get_command(typer_obj) - docs = get_docs_for_click(obj=click_obj, ctx=ctx, name=name) + docs = get_docs_for_click(obj=click_obj, ctx=ctx, name=name, title=title) clean_docs = f"{docs.strip()}\n" if output: output.write_text(clean_docs)