Skip to content

Commit

Permalink
✨ Add support for typer ./someprogram.py utils docs --title (#782)
Browse files Browse the repository at this point in the history
Co-authored-by: Jeffrey Newman <[email protected]>
  • Loading branch information
tiangolo and jpn-- authored Mar 31, 2024
1 parent ef9beaf commit bdaa5c6
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/tutorial/typer-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
102 changes: 102 additions & 0 deletions tests/assets/cli/multiapp-docs-title.md
Original file line number Diff line number Diff line change
@@ -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.
30 changes: 30 additions & 0 deletions tests/test_cli/test_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
[
Expand Down
13 changes: 10 additions & 3 deletions typer/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.
Expand All @@ -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)
Expand Down

0 comments on commit bdaa5c6

Please sign in to comment.