Skip to content
Back to top
View this page
Edit this page

# How To

The examples below all reference this example Typer application:

examples/example.py

     1import typer
     2import typing as t
     3try:
     4    from enum import StrEnum
     5except ImportError:
     6    from enum import Enum
     7    class StrEnum(str, Enum):
     8        pass
     9from typing_extensions import Annotated
    10
    11app = typer.Typer(add_completion=False)
    12
    13class Kind(StrEnum):
    14
    15    ONE = "one"
    16    TWO = "two"
    17
    18
    19@app.callback()
    20def callback(
    21    arg: Annotated[Kind, typer.Argument(help="An argument.")],
    22    flag: Annotated[bool, typer.Option(help="Flagged.")] = False,
    23    switch: Annotated[
    24        bool,
    25        typer.Option("--switch", "-s", help="Switch.")
    26    ] = False
    27):
    28    """This is the callback function."""
    29    pass
    30
    31
    32@app.command()
    33def foo(
    34    name: Annotated[
    35        str,
    36        typer.Option(..., help="The name of the item to foo.")
    37    ]
    38):
    39    """This is the foo command."""
    40    pass
    41
    42
    43@app.command()
    44def bar(
    45    names: Annotated[
    46        t.List[str],
    47        typer.Option(..., help="The names of the items to bar.")
    48    ],
    49):
    50    """This is the bar command."""
    51    pass
    52
    53
    54if __name__ == "__main__":
    55    app()

## Build to Multiple Formats

sphinx:index caches directive output and reuses the results when building the documentation to different formats (e.g. html, pdf or text). This causes problems with the way the typer directive dynamically determines which render target to use based on the active builder. This can mean that if you run sphinx:man/sphinx-build for html and `latexpdf` at the same time the pdf may not render all typer helps as expected. To work around this you can do one of four things

1. Run sphinx:man/sphinx-build for each format separately.

2. Use the `sphinx:only` directive in combination with `typer:preferred` to specify builder specific content.

3. Use the `--fresh-env` option to force sphinx to rebuild the directive output for each builder.

4. Add the following code to your conf.py to remove the doctree between builders:

   >     def setup(app):
   >         import shutil
   >         from pathlib import Path
   >         if Path(app.doctreedir).exists():
   >             shutil.rmtree(app.doctreedir)

## Change the Width

The `typer:width` parameter defines the console character length rich uses when it generates the console output. If your image is too wide, you can reduce the width by setting the `typer:width` parameter to a smaller value. For example, for sphinx-rtd-theme theme a width parameter of 65 works well:

    .. typer:: examples.example:app
        :width: 65

    .. typer:: examples.example:app
        :width: 100

## Render Subcommand Structure

Add the `typer:show-nested` and `typer:make-sections` options to the typer directive. This will render all subcommands as sections.

    .. typer:: examples.example:app
        :width: 65
        :show-nested:
        :make-sections:

### example

#### foo

#### bar

Tip

See Cross-Reference with :make-sections: for information on how to cross reference sections.

## Render a Single Subcommand

Subcommands can be rendered individually:

    .. typer:: examples.example:app:bar
        :width: 65
        :show-nested:
        :make-sections:

### example bar

## Render as HTML

By default for html builders, svg output is generated. HTML output is also supported, but requires rendering the html output into an iframe to isolate the generated css. The iframe heights can be given directly using the `typer:iframe-height` option - or dynamically calculated using selenium and a web driver. To use the dynamic height calculation, you must install the html dependency set:

    pip install sphinxcontrib-typer[html]

Otherwise provide the `typer:iframe-height` option. Use `typer:preferred` html to render the html output

    .. typer:: examples.example:app
        :preferred: html
        :width: 65
        :iframe-height: 300

## Generate Nice PDFs

By default the latex builder will convert the preferred rendering output to pdf. This may not render predictably if the necessary fonts are not installed. You will likely need to install FiraCode. You will also need to install the pdf dependency set:

    pip install sphinxcontrib-typer[pdf]

Alternatively you can convert the rendered helps to png format using the `typer:convert-png` option and passing it the builders you want to render pngs. You will also need to install the png dependency set:

    pip install sphinxcontrib-typer[png]

Any format can be converted to png - even text!

    .. typer:: examples.example:app
        :preferred: text
        :width: 90

    .. typer:: examples.example:app
        :preferred: text
        :width: 90
        :convert-png: latex|html

     Usage: example [OPTIONS] ARG:{one|two} COMMAND [ARGS]...

     This is the callback function.

    ╭─ Arguments ─────────────────────────────────────────────────────────────╮
    │ *    arg      ARG:{one|two}  An argument. [required]                    │
    ╰─────────────────────────────────────────────────────────────────────────╯
    ╭─ Options ───────────────────────────────────────────────────────────────╮
    │ --flag        --no-flag      Flagged. [default: no-flag]                │
    │ --switch  -s                 Switch.                                    │
    │ --help                       Show this message and exit.                │
    ╰─────────────────────────────────────────────────────────────────────────╯
    ╭─ Commands ──────────────────────────────────────────────────────────────╮
    │ foo   This is the foo command.                                          │
    │ bar   This is the bar command.                                          │
    ╰─────────────────────────────────────────────────────────────────────────╯

`latexpdf` often has issues with unicode characters. You may get better results using the xeLaTeX engine instead, especially when rendering text.

In your conf.py add:

    latex_engine = "xelatex"

## Customize the Rendered Output

The initialization parameters for the rich console and export functions can be overridden to provide more fine grained control over the rendered output. For example, to render a console that looks like Red Sands on OSX we can use the `typer:svg-kwargs` option, and pass an import string to a dictionary of kwargs to pass to `rich.console.export_svg()`.

examples/themes.py

     1from rich.terminal_theme import TerminalTheme
     2
     3red_sands = {
     4    'theme': TerminalTheme(
     5        (132,  42,  38),     # background
     6        (210, 193, 159),     # text
     7        [
     8            (210, 193, 159), #
     9            (  0,   0,   0), # required
    10            ( 77, 218,  77), # option on short name
    11            (227, 189,  57), # Usage/metavar
    12            (210, 193, 159), #
    13            (  0,  18, 140), # option off
    14            ( 75, 214, 225), # option on/command names
    15            (210, 193, 159), #
    16        ]
    17    )
    18}

    .. typer:: examples.example:app
        :width: 60
        :preferred: svg
        :svg-kwargs: examples.themes.red_sands

The preset Console parameters can also be overridden using the `typer:console-kwargs` option. Refer to the rich documentation for more information on the available options.

## Cross-Reference with :make-sections:

When using the `typer:make-sections` option, a section will be generated for each subcommand. You can cross reference these sections using the `:typer:` role. For example, to reference the example bar subcommand from the Render Subcommand Structure section above:

    :typer:`example-bar`

The format for the reference is `prog(-subcommand)`