2deba45588
i think it only makes sense to have an "opinion" for command line interface in this project, and we probably need more `wutta` subcommands too but we'll see. main motivation for this currently is to allow poser apps to define their own CLI, in particular e.g. `poser install`
106 lines
2.4 KiB
ReStructuredText
106 lines
2.4 KiB
ReStructuredText
|
|
Custom Commands
|
|
===============
|
|
|
|
WuttJamaican comes with :doc:`/narr/cli/builtin`.
|
|
|
|
Using the same framework, each :term:`package` can define additional
|
|
top-level :term:`command(s)<command>` and
|
|
:term:`subcommands<subcommand>` as needed.
|
|
|
|
|
|
Top-Level Command
|
|
-----------------
|
|
|
|
You must "define" *and* "register" your top-level command. Assuming a
|
|
basic Poser example:
|
|
|
|
.. code-block:: none
|
|
|
|
poser-project
|
|
├── poser
|
|
│ ├── __init__.py
|
|
│ └── cli.py
|
|
└── pyproject.toml
|
|
|
|
Add the command definition to the ``poser.cli`` module::
|
|
|
|
from wuttjamaican.cli import make_typer
|
|
|
|
poser_typer = make_typer(
|
|
name='poser',
|
|
help="Poser - the killer app"
|
|
)
|
|
|
|
Then register the command as script in ``pyproject.toml``:
|
|
|
|
.. code-block:: toml
|
|
|
|
[project.scripts]
|
|
poser = "poser.cli:poser_typer"
|
|
|
|
Then reinstall your project:
|
|
|
|
.. code-block:: sh
|
|
|
|
pip install -e ~/src/poser
|
|
|
|
And now you can run your command:
|
|
|
|
.. code-block:: sh
|
|
|
|
poser --help
|
|
|
|
But it won't really do anything until you add subcommands.
|
|
|
|
|
|
Subcommands
|
|
-----------
|
|
|
|
You must "define" the subcommand of course, but do not need to
|
|
"register" it. (That happens via function decorator; see below.)
|
|
|
|
However you *do* need to ensure all modules containing subcommands are
|
|
"eagerly imported" so the runtime discovery process finds everything.
|
|
|
|
Here we'll define the ``poser hello`` subcommand, by adding it to our
|
|
``poser.cli`` module (from example above)::
|
|
|
|
import sys
|
|
import typer
|
|
from wuttjamaican.cli import make_typer
|
|
|
|
# top-level command
|
|
poser_typer = make_typer(
|
|
name='poser',
|
|
help="Poser - the killer app"
|
|
)
|
|
|
|
# nb. function decorator will auto-register the subcommand
|
|
@poser_typer.command()
|
|
def hello(
|
|
ctx: typer.Context,
|
|
):
|
|
"""
|
|
Hello world example
|
|
"""
|
|
config = ctx.parent.wutta_config
|
|
app = config.get_app()
|
|
|
|
name = config.get('hello.name', default="WhoAreYou")
|
|
sys.stdout.write(f'hello {name}\n')
|
|
|
|
title = app.get_title()
|
|
sys.stdout.write(f'from {title}\n')
|
|
|
|
# TODO: you may need to import other modules here, if they contain
|
|
# subcommands and would not be automatically imported otherwise.
|
|
# nb. *this* current module *is* automatically imported, only
|
|
# because of the top-level command registration in pyproject.toml
|
|
|
|
No need to re-install, you can now use the subcommand:
|
|
|
|
.. code-block:: sh
|
|
|
|
poser hello --help
|