From 8a880612de45485562b443f150627a74c2b48014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 30 Mar 2024 16:55:47 -0500 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20typer=20c?= =?UTF-8?q?ommand=20--title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typer/cli.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) 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) From 908659bae6feaabd542f235d5f43715673ff1ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 30 Mar 2024 16:56:05 -0500 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=85=20Add=20tests=20for=20typer=20uti?= =?UTF-8?q?ls=20docs=20--title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/assets/cli/multiapp-docs-title.md | 102 ++++++++++++++++++++++++ tests/test_cli/test_doc.py | 30 +++++++ 2 files changed, 132 insertions(+) create mode 100644 tests/assets/cli/multiapp-docs-title.md 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( [ From 650dc4752dc30f5eb474bb3bb977f8c2763cab50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 30 Mar 2024 16:56:29 -0500 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9D=20Add=20docs=20for=20typer=20u?= =?UTF-8?q?tils=20docs=20--title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tutorial/typer-command.md | 1 + 1 file changed, 1 insertion(+) 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: