 2deba45588
			
		
	
	
		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`
		
			
				
	
	
		
			105 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			105 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
 |